Wednesday 5 February 2014

TDD: What should I test next?

tldr; focusing on the problem domain rather than the implementation will help you out

One of the guiding ideas in TDD is to implement the simplest thing that will work. This is good advice, and there is no shortage of posts explaining what it means and why you should do it. But, there's a similar question that occurs before this that always stumps me and that is 'What should I test next?'. The easy answer is the simplest behaviour that the software should have. Always testing the simplest behaviour will allow you to incrementally drive the design. Not testing the simplest behaviour tends to require big leaps in the implementation and makes it easy to get stuck a few tests in.

Initially my thought on this was that the simplest thing was the most basic arguments that I could pass in. It sounds plausible and it also got me moving quickly. The problem was that I normally got stuck after a few tests because I wasn't really analysing the problem.

It's easiest to show this with an example. I'm going to use a TDD kata called word wrap. This is the requirement:

    Break a piece of text into lines, but with line breaks inserted at just the right places to make sure that no line is longer than the column number. You try to break lines at word boundaries.

Taking the approach of using the simplest arguments would go something like this. To keep this short I'll just focus on the string argument.

First test: an empty string, column 10
Second test: a single character, column 10
third test: two characters, column 10

...and on and on. There's probably a lot of different paths you could go with this type of testing but really I was being led by the arguments rather than by the requirement. Taking it back to analysis helped me out. Initially this can be a little harder, but, you're less likely stuck because the problem domain is more likely to lead you in the right direction than the arguments for a method.

So what's, the simplest behaviour that word wrap can have? I can also ask this question in another way, what's the least amount of behaviour that I can add, while still doing something useful? The usual answer to this question for the first test is the 'do nothing' behaviour. In the case of word wrap I would think that this is a when it doesn't need to wrap at all. My specification and test name for this will be 'should not wrap a line that fits'.

The implementation that satisfies this test would look something like this:

public string Wrap(string text, int column)
{
    return text;
}

The difference between this and the previous approach is that I have one test for all lines that fit. Creating multiple tests for lines that would fit would have been pointless because I would have been re-testing the same behaviour. This is also an example of the kind of feedback that you get from your code. Not having to implement any new behaviour for a test is the code saying that you don't need that test.

Disclaimer
In this post I'm advocating the minimum most suitable tests to drive out the design. Tests should also build your confidence though, so if your instinct is telling you to add the extra tests, then go ahead and add them.

No comments:

Post a Comment