Test Driven Development is a challenging practice. Why should you bother to learn it? You should learn it because it is a productive and predictable way to develop software.
Let’s compare TDD to the most popular way of programming, something I call Debug Later Programming. In DLP, code is considered “done” after it is designed and written. After the code is “done” it is debugged. Hmmm. Interesting definition of done isn’t it? The definition fails to include about half the effort.
It’s well known that developers make mistakes during design and code. If developers did not make mistakes, they would have no need to test their code. In DLP, testing is an individualized activity that may include some of the following activities. Some single step through their code to make sure it does the right thing. Others might write a small test driver and stub out some dependencies to test their code. And still others pepper their code with logging statements and inspect the log output. The problem with these techniques is that they are inherently non-repeatable and labor intensive.
When the future changes roll in, and they will roll in, there is a big problem. Changes can have unintended consequences, a.k.a. bugs. A manual test process is very unlikely to catch all these bugs. Also, the longer the bugs lay hidden the harder it is to exterminate them.
Physics of Debug Later Programming
When the time to discover a bug (Td) increases the time to find a defect’s root cause (Tfind) also increases, often dramatically. For some bugs, the time to fix the bug (Tfix) is not impacted by Td. But if the mistake is compounded by code building on top of a wrong assumption, Tfix may increase dramatically as well.
The problem with Debug Later Programming is that the feedback, revealing programming mistakes, may take days, weeks or months to get back to the developer. By then so many changes have been made that there is often no clear root cause. The programmer’s only recourse is to start debugging. This inherently unpredictable activity can destroy the most carefully crafted plans.
In comparison, with TDD there is immediate feedback. When the changes roll in, and you have the comprehensive tests that are a product of TDD, your tests immediately tell you when you make a mistake. This immediate notification helps prevent bugs. Not all bugs, of course, but most of them.
Preventing bugs is a big deal. Not only does the delivered quality improve, but less time is spent (a.k.a. wasted) in the activity called debugging.
Physics of Test Driven Development
When the time to discover a bug (Td) approaches zero the time to find the bug’s root cause (Tfind) also approaches zero. Why? Because the problem, just introduced, is often obvious. When the cause is not obvious, the developer is only a few UNDOs away from the prior all-tests-passing state. The time to fix the bug (Tfix) is as low as it can get given that things can only get worse as time clouds the programmer’s memory, and as more code is built on top of the shaky foundation.
Why Use TDD?
Writing tests takes time. If people did not make mistakes, writing test would be a waste of time. But we do make mistakes. The time to write a test is predictable. The time to find and fix a bug is not.
How long does it take to fix a bug? I’ve heard an industry average of eight hours. That includes those one minute fixes as well as the bugs that take months to find. As a schedule owner, I would want to improve predictability, and TDD can help. I think the physics of TDD make it a very powerful technique.