After writing my last article I began to wonder what people ‘in-the-know’ thought the advantages of TDD vs integration testing were. So I quickly turned to my new favorite site stackoverflow. After reviewing several questions I came across this one entitled “Is Unit Testing worth the effort?“, and the accepted answer had 113 votes. So if you haven’t already, click the article title and read the arguments for using TDD, then read on for my responses.
Most of these apply to Integration Testing as well as TDD testing with a few that might be questionable. Let’s discuss those:
2. TDD helps you to realise when to stop coding. Your tests give you confidence that you’ve done enough for now and can stop tweaking and move on to the next thing.
Assuming your not ‘master-planning’ this should not be a problem. Write your code as-needed (YAGNI) is a principal that stands apart from TDD. This developer ‘tendency’ is also easily mitigated with requirements on test coverage %, the ‘over-engineered’ solution is less likely to be introduced if the developer is required to hit 100% functional coverage in integration testing.
4. TDD helps with coding constipation. When faced with a large and daunting piece of work ahead writing the tests will get you moving quickly.
I haven’t heard this argument before. *shrug* +1 for TDD, but I really don’t have this problem. I (and I’m most Sr Dev/Architects would agree) continually break down large tasks into small achievable goals every time I write a piece of functionality. Perhaps there is merit here for newbies, but I would guess that TDD as a whole is very beneficial for controlling the damage a newbie can cause. For the rest of us, simply writing TDD tests doesn’t mean you’ve adequately broken down the conceptual model of the coding problem.
5. Unit Tests help you really understand the design of the code you are working on. Instead of writing code to do something, you are starting by outlining all the conditions you are subjecting the code to and what outputs you’d expect from that.
I’m not sure how this applies to ‘design of the code’; however, the later part of the statement is valid. Capturing with tests the ‘behavioral contract’ of an object’s interface(s) is essential. This is and should be done by writing the client code first, even if it is just pseudo code. You should not be ‘throwing together’ interfaces without having reviewed it’s intended use. If TDD does this for you, great, I myself believe that the typical TDD (single AAA pattern) does not allow me to truly ‘feel out’ the client code. You can’t get a sense of the difficulty of using an interface is when only accessing a single method/member at a time. It breaks the flow of the intended client usage pattern into small granular chucks and that changes the things that you find cumbersome or difficult. TDD (IMO) is not a valid experience of writing the client code.
6. Unit Tests give you instant visual feedback, we all like the feeling of all those green lights when we’ve done. It’s very satisfying. It’s also much easier to pick up where you left off after an interruption because you can see where you got to – that next red light that needs fixing.
This I can totally see and agree with. Almost all developers enjoy a feeling of accomplishment from their work. Often while working on large projects it can be difficult to obtain. I think everyone needs small milestone gratification from the efforts, I enjoy the check-in to integration. As my build tells me I’m tested, working, and ready to be used, this is my moment of joy. I may not achieve this 20-30 times a day, but the two or three are very gratifying.
So in summary I again attest that TDD is cool and all, but it is not essential to a good piece of software. Testing; however, is required and the biggest thing I like about TDD is that finally got the rest of you writing unit tests :) I’ve been doing integration testing since 2000 and using NUnit+coverage since 2002 and I must say hardly anyone seemed to care about testing their own code back then.