Recycling tests in TDD

The standard way that TDD is described is as Red-Green-Refactor:

  1. Red: write a failing test
  2. Green: get it to pass as quickly as possible
  3. Refactor: improve the design, using the tests as a safety net
  4. Repeat

tdd

TL;DR; I’ve found that step 1) might be better expressed as:

  1. Red: write a failing test, or make an existing test fail

Print Diamond

One of the katas that I use in my TDD training is “Print Diamond”. The problem statement is quite simple:

Given a letter, print a diamond starting with ‘A’ with the supplied letter at the widest point.

For example: print-diamond ‘C’ prints

  A
 B B
C   C
 B B
  A

I’ve used Cyber-Dojo to demonstrate two different approaches so you can follow along with my example, but I recommend you try this kata on your own before reading further. [The link is to Cyber-Dojo’s dashboard view where you can see every change made in the source code by two different teams – Gorilla and Moose].

Gorilla

The usual approach is to start with a test for the simple case where the diamond consists of just a single ‘A’:

> PrintDiamond('A') 

A

The next test is usually for a proper diamond consisting of ‘A’ and ‘B’:

> PrintDiamond('B')

 A
B B
 A

It’s easy enough to get this to pass by hardcoding the result. Then we move on to the letter ‘C’:

> PrintDiamond('C')

  A
 B B
C   C
 B B
  A

The code is now screaming for us to refactor it, but to keep all the tests passing most people try to solve the entire problem at once. That’s hard, because we’ll need to cope with multiple lines, varying indentation, and repeated characters with a varying number of spaces between them.

Moose

The approach that I’ve been playing with is to start as usual, with the simplest case:

> PrintDiamond('A') 

A

For the second test, however, we start by decomposing the diamond problem into smaller constituent parts. This time I chose to write the following test:

[Test]
public void B_should_give_character_sequence()
{
Assert.AreEqual("AB", Diamond.Create('B'));
}

Getting this to pass solves the problem of looping over the character sequence that makes the top half of the diamond. Once that’s at green, we can then bite off character repetition, so we rewrite the test as:

[Test]
public void B_should_repeat_characters()
{
Assert.AreEqual("ABB", Diamond.Create('B'));
}

Next we go for separate lines, rewriting the test as:

[Test]
public void B_should_have_separate_lines()
{
Assert.AreEqual("A\nBB\n", Diamond.Create('B'));
}

And now, in subsequent rewrites of the same test, we can address indentation, then inter-character spaces and finally the symmetry of the bottom half of the diamond. You can follow along in the Cyber-Dojo dashboard.

Conclusion

By recycling the second test multiple times, each time modifying the expected output to become closer to what we actual want, we’ve allowed ourselves to be guided gradually to a solution.

When working on user stories, I often encourage teams to deliver low-fidelity slices early, and this is a similar strategy, but applied at a lower level. It won’t work in all cases, but if you find that the next refactor is harder than you’d like, think about trying to get there in smaller steps.


Posted

in

, , ,

by

Comments

15 responses to “Recycling tests in TDD”

  1. Darren Cauthon Avatar

    Hmm… I like it! The Moose approach looks like a good fit for those times when its hard to see an immediate step between the hardcoded answer and the final answer.

  2. […] Recycling tests in TDD Written by: Seb Rose […]

  3. […] saw that Alistair Cockburn had written a post about Seb Rose’s post on the Diamond Kata. I only read the beginning of both of those because I recognized the problem […]

  4. […] equivalently or get the same results with it. For example, take a look at the approaches used by Seb Rose, Ron Jeffries and Alistair Cockburn to solving the Letter Diamond kata. (Click on their names to […]

  5. […] Seb, Recycling Tests in TDD, Claysnow Blog, […]

  6. […] to do something very similar with product codes. But before I do that I just want to expand on (ie. recycle) the current test so that it can cater for multiple […]

  7. […] had to write Java code printing diamond, as described in Seb Rose’s post, and use git for committing the “green” code at the end of each cycle or rolling back […]

  8. […] I became intrigued with something Seb Rose said on his blog about ‘recycling’ tests. He talks about first producing a test for a ‘low […]

  9. […] เรื่อง Recycle test in TDD ซึ่งเป็นอีกแนวคิดหนึ่งในการเขียน […]

  10. […] Rose: Recycling Tests in TDD und Diamond Recycling (and painting yourself into a […]

  11. […] year Seb Rose tried to solve the „Diamond Kata“. This kata really suits the „Taking Baby Steps“ constraint because the next acceptance test […]

  12. […] The Diamond Kata is a simple exercise that Seb Rose described in a blog post on recycling tests in TDD. […]

  13. […] Original description of the diamond kata on Seb Rose’s blog […]

  14. […] ran across Seb Rose’s blog post https://claysnow.co.uk/recycling-tests-in-tdd and thought that problem would make a good […]

  15. […] well described by Seb Rose, the problem statement is […]

Leave a Reply

Your email address will not be published. Required fields are marked *