TDD is a technique that can be used as an effective design tool. However it is quite easy (or was for me) to become ”test infected”. Normally this term is used as a positive description of someone who has seen how good TDD is and doesn’t like to work without it, but in some cases this infection can turn nasty.
Symptoms of serious infection include becoming incapable of working without tests, an insatiable hunger for reference material on TDD showing the way to do it right (a worrying delusion, as there is no silver bullet), and a severe dependency on the process to the point where the patient sometimes gets blocked waiting for the tests to give them an answer to a question that they really just need to nut out for themselves.
As I mentioned in my last post on driving different aspects of code using TDD, it is really the developer using the tests to drive code, rather than the process itself driving the developer to write great code. Unfortunately severe infections can result in the developer subconciously believing the latter. Luckily the prognosis for these cases is quite positive, the infection responding quite well to simple remedial action. In many cases the patient can recover to be even more effective than they were prior to infection.
If you believe you may be suffering from a severe case of test-infection, try this experiment: force youself to write some code without using tests. High level acceptance tests are ok, just not TDD or unit tests. Something like the Karate Chop kata is ideal, because it is something that is normally very nice to drive with classical TDD tests.
When I tried this and a few similar exercises I initially found them suprisingly difficult without TDD. These were basic problems I would have solved beautifully prior to learning TDD, and here I was struggling on the same, simple exercises, all because I couldn’t lean on my favourite process. I had developed quite a severe case. I’ve also seen this experiment trip up other, far more intelligent people in the same way.
I had become a slave to the process to the point where I had surrended some of the critical thinking I used to use before picking up TDD. I actually had to retrain myself to think first by repeating a few of these simple kata-like exercises until I was able to code again without the aid of TDD. I could then use my newly-rediscovered ability to think to target how I applied TDD (or other techniques) to problems. I’m confident this process can work for other patients as well. This is not to say patients need to enjoy working without the guidance of tests, but they should be able to code and design by thinking through the problem instead of relying on TDD. TDD is a tool, not the goal.
Once a developer gets to the point where they can write decent code both with and without TDD, they are now in a great position to wield TDD really effectively as a design tool. Rather than being driven by tests, or by designing upfront or on-the-fly without the feedback given by TDD, the developer can start writing tests that push both the design and implementation in the direction he or she feels it should go. The tests aren’t driving: they are a means to an end, a stepping stone the developer uses to push the design to a point where the current feature can be implemented safely, quickly and cleanly. I think this level is where true mastery of TDD is achieved.
One day I hope to get there, but for now I’m happy to keep honing my fairly blunt use of TDD in the knowledge I’m using it to help me flounder along in the basic direction I want to go, rather than as a crutch.
Recovered from your own bout of test infection to become a better TDDer? I’d love to hear about it – please leave a comment! :)