Cultivating Quality Code - A Comprehensive Review and Notes on 'Growing Object-Oriented Software Guided by Tests'
The content here is under the Attribution 4.0 International (CC BY 4.0) license
Test driven development has been a subject of interest on this blog for a few years now and the first pot to come around was the classic book from Kent Beck: Test Drive Development by example. More recently I also wrote on my TDD journey as I was trying to focus on what would be the next steps on that.
Following this discovery, I started reading the book “Growing object oriented software guided by tests”  which as the title says focus on the development of software guided by tests, the proposal is to use a double-loop TDD - From the bigger picture to the smallest part.
If I were to give a comparison between TDD by example and GOOS I would say that on one hand, TDD by Example, focuses on shifting the mindset for testing, approaching simple problems in a way that start with test first. On the other hand, GOOS focus on expanding this idea, focusing on testing applications end-to-end.
The notes in this post are just my thoughts around the GOOS book and also questions that came up during the process, I also use the book deliberately for exposing my ideas.
The first part of the book dives into the TDD flow to give a common ground for the reader and also for the authors to build on basics before getting the book subject in place.
In this first part the Red-Gree-Refactor  is introduced as well as the idea of feedback and practices that support change. The book is from 2009 and the agile mindset was already in place (business move fast so we should adapt accordingly). Feedback is fundamental to support this mindset, TDD give developers the way to move forward fast and with confidence - Extreme programming was born with that in mind.
Steve and Nat also worked on a brief introduction on jUnit and jMock (jMock even refers to GOOS book in the home page!), this is the foundation needed to at least get started with testing. Despite of the great introduction in the book, chapter 3 is about the minimum required to know about the the tools. There are other books that gives in depth explanation around junit1, hamcrest and mocks. All in all, I felt that it was in the book as a requirement, in the end, would be difficult to start writing assertions and mocking things out without at least a minimum understanding - therefore, for beginners, this could potentially be a point of attention, if the load is heavy on this part, take the time to learn a bit more about the tools, cognitive load is crucial when learning something new.
Note on the tools: It’s been 12 years since the book was released. Aging in the word of software is not easy, things get updated and old versions stop working. For the tools or any references that I am using here, I am trying to suggest the latest version - even though they might not work with the book code examples anymore.
Part II is about getting the context again, starting from the TDD lifecycle, object oriented style and finishing up with mocking (just mock types that you own!).
Part I also goes in the introduction of TDD, here the introduction starts to get deeper, the authors introduce the idea of starting with an acceptance test and for the first time the walking skeleton is mentioned, then Alistair is quoted:
A “walking skeleton” is an implementation of the thinnest possible slice of real functionality that we can automatically build, deploy, and test end-to-end [Cockburn04].
Growing object oriented software guided by tests, Steve Freeman and Nat Price, pg 32
The idea of a walking skeleton2 is to improve feedback and starting to think about testing first, not at the function level, but rather at the whole system. Starting with that will make the process of writing tests easier. The authors quoted a project that they worked on that had never being tested end-to-end. As a result it was difficult to build end-to-end tests and usually took months to do so as the system is complex.
Key takeaway: building an application with test in mind makes it easier to keep the application maintainable and testable on the long run
In this part the double-loop TDD is stressed (in Part I this idea is already introduced) to keep following throughout the book, from here onwards this idea is the one that is explored the most, the following picture was taken from the book, page 40:
In my opinion, the walking skeleton is the most important bit for any application that is developed in a testing oriented fashion. The skeleton is the foundation in which the project will be build on, in other words, this is an architectural decision that makes clear that every bit in place is designed for testability. Not ont at the unit level, but also having a look at the application working as a whole.
We’ll start by writing the test as if all the code it needs exists and will fill in the implementations afterwards.
Growing object oriented software guided by tests, Steve Freeman and Nat Price, pg 85
Besides that I would like to elaborate on the following bullet points extracted from the book:
- Acceptance: Does the whole system work?
- Integration: Does our code work against code we can’t change?
- Unit: Do our objects do the right thing, are they convenient to work with?
Acceptance testing has different understanding from software practitioners and testers, as mentioned in the book, acceptance should be as end-to-end as possible. From my understanding, end-to-end means to use whatever dependencies needed, for instance: the database, a websocket server, cache server and so on. Earlier on, in this blog I wrote about strategies to test legacy code that goes towards this goal, there I mentioned the test pyramid as a way to give to measure how to start writing the acceptance test then moving downwards the pyramid to reach the unit tests.
Now reading GOOS, I see similarities around the approach I wrote and the one the authors presented, the XMPP server is an external dependency (more on that in Part III) that is used on the acceptance test. For me the clear message that this part gives is: feedback on the entire system is important and we should aim to work on that from the start. Faster feedback means quicker response to change and adapt if needed. Exercising the system end to end is a way to achieve that.
Personally, as we get our hands dirty in code and see the pieces fit together, in this part, the authors also share how they would approach the split of iteration for the system. Often I share the feeling that it’s not easy to deal and get the things well divided before start to code.
Even though there are some notes from both authors regarding agile planning, I think what it proposes to do is to offer a common ground for what is next rather than how to plan.
Also, for this part, the authors elaborate even more on the idea of end-to-end tests, they start to build what would be an example of an application developed guided by tests taking into account everything that has been covered by previous parts. In this part is where the “planning” comes into play, giving a better idea where to start with, as we already know that the walking skeleton, is the way to go, the authors emphasize how:
A common practice is to call this step iteration zero: “iteration” because the team still needs to time-box its activities and “zero” because it’s before functional development starts in iteration one. One important task for iteration zero is to use the walking skeleton to test-drive the initial architecture.
Growing object oriented software guided by tests, Steve Freeman and Nat Price, pg 83
In this part is where the coding takes place, starting from how to approach the first test case (spoiler alert: from the acceptance, chapter 11, “Passing the first test”). Here is where at least for me things started to get a bit blurry, as I am not a java developer that knows the in’s and out’s of swing. Basically the idea, is to provide the minimum to make the test to pass, enabling feedback, as in the authors word: “The point is to design and validate the initial structure of the end-to-end system”.
Despite of the book age (10+ years), if I were to start a project today, I would follow the same idea, enabling feedback of the system end-to-end and probably I would use docker to increase the reproducibility setup in other’s people computer.
- I found one thing that is interesting to link, this github project that recreates the auction system step by step via commits.
- This blog post is kinda a good sum up of the book, besides that the author also gives his point of view and the “the bad parts” about the book. I think that this post could be a reference for people that don’t have time to read the book.
A note on outside-in TDD
When I am coding, usually I prefer the London school. Practicing outside-in TDD is my go to for any exercise or professional work. I even built an json-tool that uses outside-in with cypress + react testing library. Anyways, it wasn’t before I gave GOOS a read, that I started to ask myself, was GOOS book the precursor for the different schools of TDD?
Was the book growing object oriented software guided by tests the precursor for the outside in TDD?— Marabesi 💻🚀 (@MatheusMarabesi) November 27, 2021
Such question came up, as I went by the book and saw this statement:
This slice is so minimal that we’re not even concerned with sending a bid; we just want to know that the two sides can communicate and that we can test the system from outside (through the client’s GUI and by injecting events as if from the external auction server).
Growing object oriented software guided by tests, Steve Freeman and Nat Price, pg 84
- S. Freeman and N. Pryce, Growing object-oriented software, guided by tests. Pearson Education, 2009.
- K. Beck, TDD by example. Addison-Wesley Professional, 2000.
jUnit in action https://www.manning.com/books/junit-in-action-third-edition ↩