Posted by Mark Withall: 2015-06-09
This is the first in a short series of articles about Test Driven Development.
- Part 1: This article
- Part 2: TDD As If You Meant It Reviewed (Part II)
- Part 3: TDD As If You Meant It Reviewed (Part III)
- Part 4: TDD As If You Meant It Reviewed (Part IV)
- Part 5: TDD As If You Meant It Reviewed (Part V)
This article was written with and is also published by Matthew Atkinson.
Part I: Introduction
Writing tests before you write any code is awesome. It means that you can rely on the code you’ve written to work (most of the time) and you can refactor with wild abandon, for example to improve performance, because it’s trivial to re-run the tests to check the code still behaves itself. However, as with pretty-much everything else, there are many ways to actually do Test Driven Development (or TDD, as most refer to it), two of which we explored in detail.
In general, the idea is that you write a test, write some code to make the test pass and then refactor (i.e. to remove duplication and otherwise improve the code’s design), before moving on to the next test. Thus, there are three stages, which are usually referred to by ‘colour’…
- RED - Write a failing test
- GREEN - Make the test pass
- REFACTOR - Improve the design of the code without changing the behaviour
GOTO 10
(i.e. repeat the above, for the next test)
In most of its forms, TDD is not a substitute for a certain amount of up-front design (though it certainly helps, as it discourages writing unnecessary code) – it’s expected that you have a good overall idea of where you’re going architecturally, e.g. that you’d have a Model, View and Controller, perhaps. You also need to decide the granularity of your red-green-refactor cycles – is a ‘red’ commit an entire test, or does it only go up to a compilation failure (e.g. where you may need to introduce a mock to take the place of a model, controller or other object – we’ll see examples of this later). There’s a lot of variation and different views on these sorts of things.
A more pedantic flavour of TDD has been proposed that caught our attention, so we had to give it a go…
What Is TDDAIYMI?
Test Driven Development As If You Meant It (TDDAIYMI) is a TDD workshop exercise devised by Keith Braithwaite. It was first presented at Software Craftsmanship 2009.
The exercise aims to apply TDD in the most pedantic way possible; to stretch one’s programming muscles. It is not intended that this extreme approach is used on a daily basis, for real-world programming tasks.
TTDAIYMI takes the form of a re-phrasing of the standard TDD steps, as follows (taken from the original article, see above).
The Rules
- Write exactly one new test, the smallest test you can that seems to point in the direction of a solution
- See it fail
- Make the test from (1) pass by writing the least implementation code you can in the test method.
- Refactor to remove duplication, and otherwise as required to improve the design. Be strict about using these moves:
- you want a new method – wait until refactoring time, then… create new (non-test) methods by doing one of these, and in no other way:
- preferred: do Extract Method on implementation code created as per (3) to create a new method in the test class, or
- if you must: move implementation code as per (3) into an existing implementation method
- you want a new class – wait until refactoring time, then… create non-test classes to provide a destination for a Move Method and for no other reason
- populate implementation classes with methods by doing Move Method, and no other way
- you want a new method – wait until refactoring time, then… create new (non-test) methods by doing one of these, and in no other way:
How Does It Differ From ‘Normal’ TDD?
There are many approaches to TDD but, for our comparison, let us take Uncle Bob’s ‘Three Laws’ approach.
The Three Laws Of TDD
‘Uncle’ Bob Martin, in his article on the Three Laws of TDD, clarifies the RED-GREEN-REFACTOR process with some restrictions upon how to follow the steps. These clarifications are as follows:
- You are not allowed to write any production code unless it is to make a failing unit test pass.
- You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
- You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
This is already quite similar to TDDAIYMI but with the added flexibility to infer the existence of production code (or at least interfaces/protocols that other production code might implement); in fact, in some ways it actively encourages it by allowing you to break up the creation of a single test into multiple RED-GREEN-REFACTOR steps, creating little bit of missing production code as you go.
Next Time
In the rest of this series we are going to write about our experiences of trying out TDDAIYMI on a small project and then comparing it to a more traditional TDD approach tackling the same problem.
Tweet Follow @MarkWithall