Sometimes, the grammar of a language doesn’t really help you to focus on the important parts of a phrase. Take “Test Driven Development” for example. It starts with the word Test and ends with Development, while Development, as a noun, is the most important part of the phrase. In French, Test Driven Development is translated to “Développement piloté par les tests”. Here, we start with the noun and the adjective comes last.
Why this short grammar lesson? Because with the phrase Test Driven Development, the most important word, Development, comes last. Test Driven Development is not a practice for testing, it’s a development method that happens to be using automated tests to drive it. You could say that the “test driven” part is nothing more than an implementation detail. So, if TDD isn’t about testing, then what is it about and why do we need it?
The reason a development method like TDD helps development is because we want to structurally write high quality code that’s readable, maintainable and most importantly, does what you want it do to and not more or less. Unfortunately, the traditional way of developing is to just think hard about a problem, come up with a solution in your mind and start writing code. And that’s not a good recipe for a good solution. So, after writing some code, we start debugging it and changing it until we think it’s correct and doesn’t produce any obvious errors.
The problem is that the solution that pops in your head first isn’t necessarily the best or complete solution, and perhaps isn’t the best next step to take. However, it often does feel like it is. We humans have the tendency to overestimate our abilities and programming is not an exception on this. If you have a lot of faith in your own mind, I’d recommend reading “Thinking, fast and slow”, written by Daniel Kahneman. After reading this book, you stop putting so much faith in the humans’ ability to rationally think about problems and start questioning your own judgement some more.
And that’s where Test Driven Development can help. It forces you to incrementally develop your solution in small cycles by making every outcome of a step explicit and think about the simplest order of steps to come up with your solution, not more and not less. To make the verification of the outcome of a step fast and easy, we use unit tests which we can run a couple of times each cycle. In TDD the developer works in a cycle where he first writes a failing test, then makes it pass and finally refactors the code. This approach prevents the developer from doing multiple things at once which can lead to errors.
But just because TDD is a development method, it doesn’t mean that you don’t get some nice side effects when practiced correctly. To start, you’ll get an extensive set of high quality tests that test the outcome (the “what”) instead of the implementation (the “how”). These tests can be used as a solid set for regression testing and can serve as living documentation. You can use them as a safety net when refactoring (reorganizing the code without changing its’ behavior) parts of the code to prevent accidental changes being made. You’ll automatically end up with a high percentage of code coverage, so there aren’t a lot of untested areas. To create production code that is testable, you’ll also end up with code that has low coupling. And since refactoring is a recurring step, we get high quality code that’s readable and maintainable. You create your solution incrementally, which leads to an Emergent Architecture instead of a Big Design Up Front (BDUF), which makes it easier to deal with changes later.
If you as a developer don’t practice Test Driven Development yet, perhaps this blog helped you to really understand what TDD is all about. And hopefully, you’re now convinced to start practicing this great development method and experience all the benefits it can bring for both you and your team.
This blog was written by Harm Pauw.