One of the (potential) criticisms of using TDD is that it takes longer to develop code when practicing it. The topic is too large to really address in depth in a blog post, but I want to touch on it here, because I think, in general, it is true, but not necessarily a compelling criticism.
On the face of it, it is obviously true in a certain respect. Writing tests to test your code requires, obviously, writing more code. Thus, since it takes longer to write more code than it takes to write less code, using TDD takes longer.
Now, as just about anyone who has written TDD attests, developing using TDD requires a change in mindset, a change in basic practice. I think this is true (though trying to quantify it is a fruitless exercise). Think about learning any substantial OOP pattern. When you start to learn and apply the pattern, it takes time because learning and applying it isn’t instantaneous. Once you understand the pattern, its application becomes natural, but before that, it requires some conscious effort that slows you down.
The same can obviously be said about TDD. When you ‘just’ write code, you write it however you write it. Forcing yourself to write tests before writing the code under test requires conscious effort if you aren’t used to it (I think some people will pick up on it almost immediately, for others, it takes longer…I’m in the middle somewhere). As it becomes more natural, you can apply the practice more effortlessly.
But you are still writing more code. So, it takes longer. Moreover, once you commit to writing tests, you commit to refactoring the tests as you refactor your code. Personally, this is probably one of the biggest time costs associated with TDD. A common ‘pattern’ that I’ve found is that you decide to refactor code to reduce repetition, and as a consequence have to refactor all of the related test code to account for this.
But (he says again), if the benefits of doing so outweigh the time cost, then it isn’t really a criticism of TDD.
Advocates of TDD have talked about the benefits much more eloquently than I, but let me grossly paraphrase some of them potential benefits as I see them.
A very obvious potential benefit is the reduction of time spent in debug mode. Especially when you are developing non-UI related code (which, MVC notwithstanding, is intrinsically harder to test), using TDD to write domain-specific logic (which is something I’m spending a lot of time on right now, so I’m focusing on that) that allows you to write code that meets its specifications (I know that ‘specification’ is a loaded term, but let’s go with it) much more quickly, without having to jump into the debugger to determine that your code does just that. I will admit that I still, on occasion, will jump into the debugger, in part because I know that I am not currently totally confident in my test-code writing ability, but that is a ‘criticism’ of me, not TDD.
People like Derik like to talk about the ‘safety net’ of testing (the term ‘safety net’ comes from another Alt.NET’r from the Chicago group but I think it matches what Derik has expressed in the past) and I know what that means. I recently worked on a project where (for various reasons) I could write tests for half of it, but not the other half (it would be comical to explain why, but would take too much time and probably violate an NDA or something). Because of the tests that I had for the first part, I was much more confident (not totally, see above about my self-assessment at test-writing) that I would not get bugs from the QA department about that part, as opposed to the part where manual testing was required. Both ‘parts’ were non-UI related, but only the testable part could be, well, tested, independently from other people.
That right there indicates a way in which the benefits of TDD can become more apparent. TDD allows you to write code that doesn’t require other people for immediate verification (you always need later verification, but that is true of any code in just about any situation).
The biggest potential benefit is that you can prevent the bugs that the QA department will surface in the first place. You could argue that this is, in fact, the real point of TDD.
I am ambivalent about this. Without something like BDD-style specifications (I don’t like a single implementation of BDD that I’ve seen, but the core idea behind it seems solid), I think this is a hit-or-miss proposition.
In any event, I don’t think the ‘using TDD requires more code’ is really much of a criticism, by itself. As a big fan of using MVP with WebForms, I know that using the MVP pattern requires more code, and as I’m writing it, I’m often annoyed about it, but I think the benefits of MVP outweighs the cost. Similarly, the same should hold with TDD (or some form of it, anyway).