QWAN logo

Story Cycle, Driven By Tests

Tags: test driven development, acceptance test driven development, behaviour driven development

We often use the diagram below to explain how the small loops in TDD (Test Driven Development) fit into our overall way of working. The diagram is a variation on a diagram from Lasse Koskela’s book “Test Driven”. Apart from the book, we could not find an online version of this diagram, so we are putting it here, with a brief explanation as we would do this in our Test Driven Development course.

Story cycle, drawn by  Marc Evers.

We use this diagram in our courses to set the stage for TDD. While we focus on the test-fail-pass-refactor cycles on the right, having intent developed in close collaboration with stakeholders is not optional.

Let’s go through the loop from left to right. In a sense, there is an Outer loop, comprised of collaborating with customers, which includes the Inner loop, where developers move the code forward to the point where they can have a conversation with stakeholders and ship it. Or in a high-trust environment, developers ship it and have the conversation later.

Nothing stops us from having conversations with the stakeholders all the time. Small, controlled steps help developers be more responsive to users’ needs. Customer acceptance at the end of the loop is a form of MVC - Minimum Viable Communication.

The outer loop

Tell a user story

This is deliberately phrased as tell, not write. We like Ron Jeffries’ Card, Conversation, Confirmation heuristic. Developers have a conversation (or more if needed) with the stakeholders. They write things down on index cards or post-its. That is because not much can be written on a card, so it is simply a token for future conversations. Acceptance tests provide confirmation.

Define acceptance criteria & tests

So we sit down with the stakeholders, and ask if we can have access to the users. We ask them what would it look like when this is done. See Ron Jeffries’ Card, Conversation, Confirmation text for more detail.

Implement acceptance test

We may choose to implement the acceptance test in code, in one form or another. When we model our domain well, these can be fast running tests. We do not need to spin up a whole application or a set of services to run these. Formalising these tests will reveal our lack of understanding quickly and trigger more conversations with the stakeholders.

When we implement the acceptance tests, we do this one at a time, preferably in an order that allows us to ship each one individually.

Failing acceptance test

Then we have one failing acceptance test. Since we need to go through the inner loop multiple times, we want to have momentum, a constant sense of progress. So for acceptance testing, we also apply the TDD Heuristic of One failing test at a time.

Inner loop

Going through the inner loop multiple times, developers create working, sustainable software, one failing test at a time. We will describe the inner loop details below.

Passing acceptance test

Then we have a passing acceptance test. We celebrate, and let out a sigh of relief. We have something that we can ship. This is also a good time to step back.

Take-a-step-back refactoring

In the inner loop, refactoring happens all the time. Now that we have something visible and cohesive from a users’ perspective, we take a step back and see if we can improve the cohesiveness of the design from a developers’ perspective. Our future selves and our colleagues will be grateful for this.

It is also fun, because the pressure to get something done is off, we often gain some more perspective, and can play around with the design, as it is expressed in the code.

Customer acceptance

We like continuous delivery, so we go back to our stakeholders for acceptance as soon as possible. In a high-trust environment we ship immediately, and notify the customer after. In a lower trust environment, or when processes dictate, we will ask for acceptance first. But we rarely wait until the end of an arbitrary time period. Small changes shipped frequently are more reliable, and if we make users (un)happy, we would know rather sooner than later.

Ship it and on to the next iteration of the loop

Ship it has been mentioned several times, and may have happened already.

You may be familiar with this loop as Behaviour Driven Development (BDD) or Acceptance Test Driven Development (ATDD).

The inner loop

This loop is still best learnt by doing, so we will keep it brief here. In our training courses we explain the loop briefly, and as we practice through a series of exercises, we share TDD Heuristics: rules of thumb based on what we and the participants observe.

Write a test

We write a single test, we apply Wishful Thinking about the functionality and interface that we want. We look for the smallest step will move us forward and that will teach us something about the design.

Make it fail

Then we make the test fail. We inspect the failure message for clarity. Will our future selves understand the message? Will our colleagues?

This step is also important, because some test frameworks occasionally fail to pick up new tests. This keeps us in the loop. Occasionally we find out, especially in larger systems, that the functionality we want already exists. Then it is back to the drawing board, there might be more that we can use.

Make it pass

We take the smallest step forward to make the test pass. We apply the Faking & Cheating heuristic. This often helps discover some tests that we missed. We add them to the test list, and move on.

Refactor

We improve naming, remove duplication. We also extract common setups and ensure the names of the set of tests read a bit like a specification.

Further reading

Emily Bache calls this way of working Double Loop TDD. Her Double-Loop TDD Learning hour uses a similar diagram of the cycle, with fewer parts. If you want, you can play ’spot the difference’. I only found her naming of this cycle from 2013 this week, as someone asked a question about it. I structured today’s explanation into an inner and outer loop, which makes it easier to outline in a post. In a live setting we tend to work left to right, starting from ’tell a story’ and then go round the circle.

You can find some concrete advice on how to ’ship it’ in Feature toggles, no thank you, I’d rather ship piecemeal.

Ron Jeffries’ blog post Card, Conversation, Confirmation goes into more detail on the conversation.

Our earlier post Three feedback loops in software product development introduces a feedback loop based perspective. We can map the story cycle on the three feedback loops:

  • the left side interacts with the product loop;
  • everything in the story cycle fits in the ’working together getting things done’ loop;
  • working in small, reversible steps fits in the technical excellence loop, enabling the other loops to be more agile.
RSS feed icon RSS feed