In this project, we are exploring how to make the TDD process more efficient and easier to learn, by using code generation techniques to automate some of the more mechanical parts of the process.
What is TDD?
In Test-Driven Development (TDD) the code needed to implement a feature (the “production code”) and the set of test cases that describe its correct execution (the “test code”) are created together, in lock step. We proceed by interleaving the writing of unit test cases describing increments to the functionality with the modification of the production code to make each test pass. We do this by following a few simple rules:
- New behaviour can only be added to the production code in response to a unit test that is failing (indicating that the production code implementation is missing some required functionality).
- When changing production code to make a failing test pass, we should aim to make only the minimal changes needed to achieve that, without concerning ourselves with wider design quality.
- Once a test is made to pass, we review both the test code and production code, looking for ways to improve the quality and ways to generalise the implementation to cover the full feature embodied by the test cases.
This gives a three step cyclic process, often referred to as the test-code-refactor cycle, or the red-green-green cycle (after the colour labels of the test results expected after each stage).
By following this approach, we grow both the implementation and the test suite to fit the requirements, aiming to create only the tests and production code needed to deliver value to the client. TDD results in code with a high test coverage, strong correctness, and a lean implementation focused on the requirements. But it can be challenging to apply, requiring both discipline and creativity.
What is Test Only Development?
Some of the steps in the TDD process are quite mechanical, while others require a solid grasp of software design and refactoring skills. Especially in the early stages of the implementation of a new feature, the “code” step of the test-code-refactor cycle can involve using the same technique repeatedly, in a way that does not require much thought or insight.
We hypothesise that some aspects of the TDD cycle can be automated, using code generation techniques. In this project, we were able to demonstrate that that is possible for certain cases of the “code” step of the TDD cycle.
Benefits of Test-Only Development
While the obvious benefit of TOD tools might seem to be general coding efficiency, there are also potential benefits for learners of TDD. TDD is known to be a challenging technique to learn. Our experience of teaching TDD to undergraduate students is that learners struggle initially with writing the minimal production code needed to make tests pass, as well as with the refactoring step that follows. TOD techniques can help learners by showing them alternative approaches to their own next step, that may be more minimal and a closer match to the tests than what they have come up with.
We are also beginning to use some of these techniques in analysing the work of professional coders, to learn how TDD is used in practice and how closely the processes are followed.
A further potential benefit is that TOD may give a half-way house between manual coding and automated code generation techniques, in which the human coder and the code generation tool set work together.
Publications
Armitage L., Test-Only Development, BSc Project Report, The University of Manchester, 2015.
Embury S.M., Borizanov M. and Jay C., Red-Green-Go! A Self-Organising Game for Teaching Test-Driven Development. In: Parsons D., MacCallum K. (eds) Agile and Lean Concepts for Teaching and Learning. Springer, Singapore. 2019.