Why Test Driven Development?
Test Driven Development (TDD) approaches the production of code in a different way, it enables the developer to consider the writing of code from a user perspective. At Boost we find TDD incredibly useful for emphasising the focus on user centered design of code. The test takes into account what the function should achieve rather than testing that a piece of code works.
By beginning with writing code to satisfy a function, the developer is approaching the function as a whole and will often make assumptions on how it should behave, this can lead to extraneous code as well as the omission of code. Although a test written after code may succeed, the resulting functionality may not satisfy the user requirement. Writing tests prior to the writing of code encourages the developer to focus on what the functionality specifically needs to achieve. The test informs the writing of code rather than the code dictating the writing of the test. TDD is not just testing that code works, it’s also testing that a user requirement is met.
Writing tests first can also help reduce the psychological impact of writing and amending code in that if the developer is confident they understand the requirement, they can then write a very specific test and be more confident the code they write will succeed. Writing code against specific criteria is a far more structured and therefore less risky way to produce code.
What is Test Driven Development in practice?
Test Driven Development (TDD) is a way of writing code that starts with writing a test as opposed to writing code. It’s often referred to as an outside in approach because a test is written and run prior to the writing of production code. The initial test should fail, if the test does not fail it should be rewritten until it does fail. Once the test has failed production code should be written and the test re run. If the test fails the developer goes back to the code then reruns the test in a cycle until the test succeeds. Once the test has passed the code is cleaned up and the process is restarted for the next unit of code. As development progresses all previous tests as well as the latest test are run each time new code is tested to ensure the code is integrated without breaking anything.
A simple way of remembering the process is to remember Red, Green, Refactor. In other words, the test must first fail (red), code is written, the test passes (green) and then the code is refactored. The TDD process is illustrated below:
What effect has TDD had on the production of code at Boost?
Using TDD to produce code means that developers begin by setting out exactly what the code should do rather than beginning with how the code should satisfy the requirement. The advantage of this is that the developer is focussed on what the code needs to achieve from the outset rather than writing code in a more generalised way. At Boost we’ve found that continuous testing quite naturally results in fewer defects and TTD results in a greater understanding of what the code should achieve as well as cleaner code.
How does it work alongside Behaviour Driven Development (BDD)?
BDD is used to test an entire feature whereas TDD test actions or units within a feature, they work together in the following way: If all unit tests pass but the feature test fails, a new unit test should be written and the cycle of writing code and running unit tests should be run until the unit test passes. The feature test should then be re run, if it still fails, the developer goes back to the TDD process and so on until both the unit tests and the feature test pass. This is shown in the diagram below:
How does TDD fit in with Agile processes?
One of the principles of Agile is to inspect and adapt, TDD fits in with this principle as the process is a continuous cycle of inspection through testing and adapting of code to achieve successful tests. TDD can also help to reduce the likelihood of technical debt as the process includes a refactoring step in each cycle.
At Boost we find that TDD not only reduces the chance of code defects, it also fits in well with our Agile practices and in conjunction with BDD, gives us confidence in the resulting code and functionality.