Test-Driven Development, or TDD, is one of the best practices of eXtreme Programming (XP). Test-driven development is a development method for software in which tests are written first and then the code. The name test-driven development is derived from Kent Beck, who put this technique on paper in 2002 and is credited for rediscovering the technique [Beck 2002]. The original description of TDD was written by D.D. McCracken in 1957 [McCracken 1957].
TDD has a lot of impact on the way in which development testing is organised these days. It is an iterative and incremental method of software development, in which no code is written before automated tests have been written for that code. The aim of TDD is to achieve fast feedback on the quality of the unit.
The development cycle below is based on the book Kent Beck's book. This cycle can be repeated as many times as needed to make the code fully functional according to the requirements.
Creating a test
- Write a test
TDD always begins with the writing of test code that checks a particular property of the unit based on a requirement, and then the code is written.
- Run all tests run and see if the new test fails
This test should initially fail, as the piece of code to which this test applies does not yet exist. The failure of the new test is important to determine whether the test is effective (contains no errors and therefore always succeeds).
Encode and test
- Write the code
Write the minimum code required to ensure that the test succeeds. The new code, written at this stage, will not be perfect. This code may only contain functionality that is necessary for the test to succeed. This is acceptable for the code does not have to be written perfectly, as long as it works. It is important that the written code is only designed to allow the test to succeed; no code should be added for which no test has been designed. In the subsequent steps the code will improve on it and rewritten according to the standard.
- Run tests and see if they pass
- In this step, all tests, new and all the previously created tests are run again to see if all tests pass. If this is the case, this will be a good starting point for the next step. The developer knows that the code meets the requirements included in the test.
- Rewrite the code The code is cleaned up and structured without changing the semantics. Also, any duplicate code necessary to minimize the interdependence of the components will be removed. The developer regularly executes all the test cases. As long as these are successful the developer knows that his amendments are not damaging any existing functionality. If the result of a test case is negative, he has made a wrong change.
The application of TDD has a number of big advantages. It leads to:
- More testable software
The code can usually be directly related to a test. In addition, the automated tests can be repeated as often as necessary.
- A collection of tests that grows in step with the software
The testware is always up to date because it is linked one-to-one with the software.
- High level of test coverage
Each piece of code is covered by a test case.
- More adjustable software
Executing the tests frequently and automatically provides the developer with very fast feedback as to whether an adjustment has been implemented successfully or not.
- Higher quality of the code
The higher test coverage and frequent repeats of the test ensure that the software contains fewer defects on transfer.
- Up-to-date documentation in the form of tests
The tests make it clear what the result of the code should be, so that later maintenance is made considerably easier.
The theory of TDD sounds simple, but working in accordance with the TDD principles demands great discipline, as it is easy to backslide: writing functional code without having written a new test in advance. One way of preventing this is the combining of TDD and Pair Programming; the developers then keep each other alert.
TDD strategy for testing GUI
TDD also has its limitations. One area where automated unit tests are difficult to implement is the Graphical User Interfaces (GUI). However, in order to make use of the advantages of TDD, the following strategy may be adopted:
- Divide the code as far as possible into components that can be built, tested and implemented separately.
- Keep the major part of the functionality (business logic) out of the GUI context. Let the GUI code be a thin layer on top of the stringently tested TDD code.
TDD has the following conditions:
- A different way of thinking: many developers assume that the extra effort in writing automated tests is disproportionate to the advantages it brings. It has been seen in practice that the extra time involved in test-driven development is more than made up for by the gains in respect of debugging, changing the software and regression testing.
- A tool or test harness for creating automated tests. Test harnesses are available for most programming languages (such as JUnit for Java and NUnit for C#).
- A development environment that supports short-cycle test-code-refactoring.
- Management commitment to giving the developers enough time and opportunity to gain experience with TDD.