TDD is a "pay me now or pay me later" tradeoff. If you only count the time from starting coding to checking in your code then TDD often does take longer, especially when first learning TDD. The payoff comes later during the testing phase, and also in future rounds of coding.
For the testing phase, I found that with TDD:
- I had substantially fewer bugs. My last TDD code I had bugs only due to requirements misunderstandings (or changes) or in the areas where I wasn't able to bring the code under test (PHP code in that case).
- The bugs I had were generally easier to reproduce under test, because I had already gotten the system under test.
- Fixing the bugs was faster, and with the tests I could have a greater belief that I didn't introduce new bugs.
The code itself had the following properties:
As I started out thinking like a client of the code, the code tended to be easier to use. (This is one of the benefits of writing tests first).
The code is easier to test.
Writing unit tests is easier (and in many cases more fun) just before rather than after, so more tests are written.
The code is easier to refactor and clean up. This was particularly true with Python, where automatic refactoring tools have a harder time.
Because of that, when it came time to revisit the code, it was easier to understand and easier to change, plus we had at least some regression tests already in place.
What this means is that the payback for TDD time may be months later. Furthermore, starting TDD with legacy code is particularly hard. Then there is time needed to both learn how to write good tests (a bad test set can either be insufficient or worse be brittle making it harder, not easier, to do refactorings) and how to get a complex system under test.
I have to admit I haven't been really able to get too many other people to switch to TDD. I think I switched largely because I wanted an easier way of testing and also I had the opportunity to learn how with a small code base and personal project.