Growing Object-Oriented Software, Guided By Tests (chapter 4)

Feb 07, 22

Inspirational quote time:

We should be taught not to wait for inspiration to start a thing. Action always generates inspiration. Inspiration seldom generates action. Frank Tibolt

How do we get started with TDD on a brand new system? The authors recommend building a ‘walking skeleton’. This means we should try and get the full deployment pipeline and our environments set up (and tested) as soon as possible.

By building a walking skeleton, we will be able to introduce end-to-end testing early. This will help to catch regressions, and should also help to influence the shape of our system.

We should be able to design the walking skeleton (at a high level) on a whiteboard within a few minutes. It just needs to be a broad picture of how the system will function, and its major components.

At this point it would help to have a high-level view of the client’s requirements, to guide us towards the prototype.

Edd’s note The client could be yourself!

At a high level, the initial process could look like this:

  1. Understand the problem
  2. Broad brush design (architecture)
  3. Automate (Build / Deployment / end-to-end tests
  4. – Deployable system –
  5. Now start acceptance/feature/unit testing as the system grows.

All of the design shouldn’t be upfront though. We just need a deployable skeleton so we can start testing.

Basically - Do the minimum amount possible to get a deployable system up and running to allow for the test cycle to begin.

We should make an initial release as soon as possible, and get feedback from stakeholders about the design.

Use the feedback to confirm if we are heading in the right direction.

We should seek to repeat the above checklist on every early release - use actionable feedback to guide the design decisions. Do not rely on a big bang release. Be agile.

In the process, check the implementation of the system and refactor if required. Do not get too tied to an idea at this early stage (remember that the only constant in software engineering is change).

A strong test suite will help during this design process. Any regressions that are introduced during refactoring should be caught by the automated tests. We should be able to make major changes safely.

It can take a long time to get a refined walking skeleton up and running. This is because early requirements can usually be quite nebulous. A lot of effort must be expended to extract the domain logic and codify it. It can be surprising how long it takes to go from 0 -> walking skeleton. Must be prepared for this and persevere. Build the test suite on a strong foundation.

There is a graph in the book of how this process looks, but basically, the test-first approach introduces a lot of work and questioning at the start of the project and then settles into a predictable routine of test -> release -> deploy -> test etc. Then at the end of the project, there may be a little more activity to add the final touches.

The opposite approach (just starting the project without a robust test -> release -> deploy process) appears to start off calmly but gets progressively more busy/stressful as time goes on. Leading to a ‘crunch time’ scenario near release time. A team may be dealing with a raft of problems at this point, and not having a robust test suite will make things a lot more difficult. This will make all parties involved very stressed.

The walking skeleton will flush out issues early in the project when there’s still time, budget and goodwill to address them.

If we are working on an existing project (brownfield) with no tests, we should seek to build a walking skeleton around the project. Create end-to-end tests and an automatic build/deployment system. Then try to test from the outside in as new functionality is added