I’m often hearing thoughts about Test Driven Development from people not using it, which are not true (at least not 100%).
Therefore, I want to describe some of these myths here:
- Writing unit tests is difficult and complex
- Projects take longer because of the additional test code that has to be written
- Not everything can be tested with unit tests. Therefore TDD cannot be used.
- There is no need for architecture and design because TDD claims to evolve that from tests
Now, let’s have a look why these are myths:
Writing unit tests is difficult and complex
I often hear this from people who either haven’t written any unit tests at all or have written unit tests after writing the production code.
In the first case, it’s simply hearsay or fear of the new. In my workshops, I make an example how TDD unit testing works and the reaction is normally “ah, that’s easy and straight forward”.
In the second case, I agree that writing unit tests after the production code is often very difficult. But this is not caused by the unit test itself. It’s the structure of the production code that is not fit to be testable – at least not simply. Therefore, when writing unit tests in a test first (or better writing test and production code at the same time) a approach, the unit test code does not have to follow the structure of the production code, it defines the structure of the production code. And because you have all the freedom to write your test in a simple way, writing them gets easy. That has a second significant consequence, too. If your unit test code is simply then it’s likely that the clients of your code (= other code that calls your code) will be simple, too. Thus leading to less overall complexity.
Projects take longer because of the additional test code that has to be written
Yes, there will be more lines of code if you use unit tests.
Yes, it takes time to write unit tests.
But, what about the efficiency of writing code?
If you use TDD then you will become more efficient in writing code. There are two main reasons for this:
- Immediate feedback from unit tests
- Developing code in a unit test corset allows parallel development and less debugging and testing roundtrip time.
Your unit tests will say you whether what you just programmed in the last 2 minutes is correct (assuming your unit tests are okay) or not. Ever feared a refactoring? Not anymore with the code coverage TDD will give you. Just try it and see what your tests will say to you. Furthermore, your unit tests define how your code wants to be used – not your code defines how it has to be used. That’s a big difference for your colleagues using your code! Your unit tests give you the feedback whether you did well or bad, just with about one click.
The unit test corset gives you another important benefit. You do not need to start the application, navigate through menus and dialogs until you reach the functionality to just programmed – maybe even needing the debugger to see whether your code is actually called. With unit tests, you reach your code within second; thus reducing the roundtrip time of a feedback loop from minutes (in medium to large systems) to seconds (independent of the project size).
Not everything can be tested with unit tests. Therefore TDD cannot be used.
Sure – not everything can be tested. It even does not make sense to write unit tests for everything. Writing unit tests makes sense if the additional test rises your faith in your code or reduces fear of failure.
Furthermore, we don’t just use TDD. We also write unit tests
- after the production code (pure verification tests) – called POUTing
- after finding bugs to resolve them and make sure they stay away – called DDT
There is no need for architecture and design because TDD claims to evolve that from tests
There are quite a lot of people out there who claim that with TDD the architecture and design will evolve. That’s simply not true. Or do you think that you can let a team of 10 developers start without a defined architecture? The code parts (classes and components) produced by these developer will probably not fit together. And where to start writing a test for, at all?
We do not drive design and architecture with TDD. We drive implementation. The architecture and design have to be defined before writing the first test. This gives the team the boundaries they need to be focused while driving the implementation with unit tests.
What TDD gives you is early feedback about your architectural and design decisions.