Test-Driven Development (TDD) was created originally as part of the Extreme Programming (XP) methodology, where it was known as the ‘Test-First’ concept. When using TDD, developers write unit tests before the code is written which helps flesh out the requirements detail; detail that can then be used to produce a better solution. You can read a more detailed description of TDD here.
Figure 1: General flow using TDD
There has recently been an outbreak of criticism of TDD, to the point where some have claimed that TDD is dead! Is this a real reflection of trends in testing practice, or noise intended to draw attention? It seems that those sounding the death knell for TDD do so by using such a rigid definition of TDD that it becomes so narrowly applicable as to be almost useless. Having lost its usefulness, it can be declared dead.
This is the problem with ideas that begin as useful concepts but are then slowly strangled by those who would have those ideas defined and specified down to the last atom. Agile principles are simply not like that. Agile ideals encourage adaptability, change and choice. The claim of the TDD demise also comes with the idea that we are either writing test-first software or we are not.
Why does it have to be so black and white? Why can’t we do test-driven development where it works and use other methods where it does not, all at the same time? When we travel from A to B, we don’t stick to just one method of transport, even if we love cars. Sometimes we walk, sometimes we fly and yes, sometimes we will drive. It should be the same with software development; we need to get from A to B and we shouldn’t limit ourselves by saying that we must only use one method to get there.
Many aspects of software cannot be tested using more code anyway! Somebody recently told me, “Just because there are exceptions in which this won’t work, doesn’t mean we shouldn’t gain the benefit from those times that it will.” TDD does not preclude the need for other types of testing and we can take our pick as to which we use; user acceptance testing, stress testing, code reviews and of course, manual & exploratory testing, are all examples from a much longer list.
The claim has been made that serious investment in TDD leads to the neglecting of system or acceptance testing. This is like saying that manufacturers shouldn’t put automatic breaks on cars because drivers won’t bother to apply the manual brakes themselves. Quite ridiculous! We can lessen the risk if we realize that TDD is not purely a testing method, it is a development method; it is an aid for developers to help them develop a greater understanding of the requirements and then be sure that at the most granular level, those requirements are met. Thinking of TDD as a development method ensures that we have an independent and comprehensive testing philosophy. Perhaps we wouldn’t be having this discussion if the TDD had been called something different, such as Demonstration Driven Development; the ‘3D’ method.
Figure 2: Separating Coding from Testing
If TDD was working for us at one time, and now it is not, (although I’m not saying this is the case) something has changed. Rather than throw out the baby with the bathwater, why not put some effort into understanding what has changed and correcting it? Perhaps we’ve simply forgotten the original spirit of TDD and need to find our way back. But from looking at the debate from both sides, I can only conclude that it’s really just a lot of noise about something that generally is working well.