Test-Driven Development (TDD)

Effective Agile teams use a technique called Test-Driven Development (TDD), in which the unit tests are written before the code. Then, just enough production code is written to allow the test to compile, but not pass. The unit test is executed to ensure that it really does fail. If it passes at this point, then the unit test must have a problem. Then code is written until the unit test passes. The code and tests are then Refactored to eliminate duplication, minimize dependencies and better express the intent of the code.

While the concept of TDD sounds simple, it requires a considerable amount of discipline and focus, although this becomes much easier over time. The unit tests must be kept as small as possible so that the code required to make them pass is similarly small. The end result is a comprehensive test suite that can be executed at any time, and code that tends to be much cleaner since it has been focused from the start on simply making a test pass. This concept is known as coding by intention.

Specification, not Verification

In Test-Driven Development, the tests are not used for verification of the code, but rather for specification, i.e. the tests detail how the code is supposed to behave. Indeed, people are now beginning to use the term Behaviour-Driven Development, with associated tools. Even the latest version of the quintessential Java testing tool, JUnit, no longer forces the developer to begin the test method names with ‘test’.

The TDD Cycle – Test-Code-Refactor-Integrate

TDD follows a consistent rhythm or cycle as illustrated here:


  • A small test is written to express some behaviour for the class
  • Just enough code is written to enable the test to pass
  • The code and test are refactored to eliminate duplication and minimize dependencies
  • The code and the test are integrated with the rest of the system, which generally entails pulling the latest updates from source control and executing all tests to verify that the new test and code do not break any existing code

It’s important to emphasize that this process occurs in very small steps. A single test and accompanying code are written, executed and integrated with the rest of the system. By making only tiny changes like this, collisions during the integration process are much less likely and much easier to resolve.

comments powered by Disqus