Test-Driven Development and Software Quality

how-to
May 26, 20083 mins

Any Test-Driven Development practitioner will tell you, Test-Driven Development is a design strategy, not a unit-testing technique. Writing unit tests are a means, not an end. The goal is to write better quality, more reliable, and more accurate code.

I recently read a study in the IEEE Software journal (“Does Test-Driven Development Really Improve Software Design Quality”, IEEE Software, March/April 2008), by David Janzen and Hossein Saiedian, that tried to establish measurable benefits of Test-Driven Development on software design quality. Now any TDD practitioner will tell you – using TDD properly tends to produce better quality code. Not just code that is tested better, but well-designed code.

This study looked at TDD as an isolated practice, independent of other agile practices. Indeed, TDD isn’t limited to Agile development – you can also do TDD in more traditional development processes. Just replace the “Detailed Design -> Code -> Unit Test” cycle with “Unit Test -> Code -> Refactor”.

Not suprisingly, teams that practiced TDD obtained much better code coverage statistics. But, more interestingly, the study also found that coding teams that practiced TDD tended to implement smaller, simpler solutions, with less lines of code overall, and less lines of code per method. The cyclometric complexity was also lower, which is a side-effect of simpler, more testable code. My own experience, like a lot of TDD practitioners, tends to bear these finding out. However, it is hard to come up with objective evidence, since you rarely solve exactly the same coding problem in the same conditions twice.

Testable classes tend to be more modular, configurable and flexible. My gut feeling tells me that classes coming out of a TDD approach are more loosely coupled. TDD is a nice fit for techniques such as Dependency Injection and the use of interfaces, which encourage more loosely-coupled and more flexible components. The study did not provide any hard evidence of this, however. The authors speculated that this reflected the fact that TDD developers use a “good” kind of coupling, using interfaces and abstract classes. This “good” coupling results in more flexible components, rather than more rigid applications.

So, basically, there is some objective data indicating that TDD promotes better quality code. This makes sense. When you practice Test-Driven Development, you think about how your class will be used by other classes. Go far enough and you should get to a precise user requirement – otherwise, what are you coding for? Just writing code without any thought to design or testing is just hacking. When you do traditional up-front design on paper before you code, you won’t think of everything, and the original design often bears little ressemblance to the final implementation. On the other hand, writing, or at least envisaging, your unit tests helps you flesh out a clean and efficient design for your class. You can jot down UML sketches to help formalise your ideas, but there is no substitute for trying to write the code that actually uses your class.

One interesting exception is the domain model, which often lends itself well to careful up-front modelling, though even this will evolve throughout the life of the project.

John is principal consultant at Wakaleo Consulting, a firm specialising in Enterprise Java, Web Development, and Open Source technologies. He is currently based in Wellington, New Zealand. Well known in the Java community for his many published articles, and as author of Java Power Tools, John helps organisations to optimize their Java development processes and infrastructures and provides training and mentoring in open source technologies, SDLC tools, and agile development processes.

More from this author