Actually I thought it was an atrocious article, full of sloppy thinking and riddled with condescension. These twelve supposed benefits of TDD range the gamut from ridiculously untrue (“unit tests prove that your code actually works”) to personal preferences (“it’s more fun to code with tests than without”), to unscientific generalizations from limited personal anecdotes or perhaps selected case studies (“it’s faster than writing code without tests”), to solutions to problems few people encounter (“it virtually eliminates coder’s block”). He lost me LONG before the last sentence.
No, I’m with James Bach. There are No Best Practices; a “Best Practice” is a rule devoid of context. As Andy Hunt points out in his awesome presentation, “Herding Racehorses, Herding Sheep”, context-free rules are only the first stage towards holistic comprehension. They’re great for novices, but experienced practicioners violate these rules all time. In chess, for example, a beginner might learn “never lose a piece without winning a piece of equal or greater value” - and that piece of advice, if taken to heart, will improve their game a great deal. But it’s not a silver bullet. In fact, their chess ability will reach an early plateau if they don’t start learning the situations in which they NEED to sacrifice material in exchange for position.
When I hear someone say, “we should use TDD all the time”, it’s very clear to me that they’re a software engineering novice. They haven’t quite understood in what circumstances TDD works best, which circumstances it has no effect either way, and yes, in which circumstances it’s just a plumb waste of time.
Where does TDD shine? TDD works best in new “from scratch” development, in code which lends itself to well-defined, testable outputs (eg, text or API calls, not-eg UI or AI algorithms), in code which is algorithmically simple enough to run in sub-millisecond times, and in code which is largely self-contained (rather than dependent on a network, database, or large object model environment or outside framework).
Let’s face it. These are very limiting criteria, and there’s a lot of real-world code which can’t be shoehorned to fit this model. Don’t think that because TDD worked so well for you in your college project or cool little app that you wrote, that it’s the One True Way that All Development Must Be Done.
I have been written to write a developer test from time to time. Who hasn’t? Sometimes it’s a unit test, sometimes it’s an system integration test (testing the interfaction of several units). But I don’t write tests for everything. Like I said, some code I simply can’t test. Other code is so simple, I’d be wasting my time trying to test it. But beyond that, I’m in the practice of looking at the bugs that I myself, or my coworkers have written, and asking myself, “how could this have been avoided”? And the answer is almost never “a unit test would have caught that”. I just don’t see where the ROI is in banging out all these tests that don’t catch anything.
And quite frankly, the few merits TDD has (“unit tests make better designs”) is a level of hand-holding I outgrew long ago. I’ve learned (mostly from painful experience maintaining other people’s code) what code smells I should avoid. The question “how should this function be used?” comes far more naturally to me than “how should this function be implemented?”. I don’t need TDD to force me to think that way. I know to keep my objects small, to write referentially transparent code, to not write Rube Goldberg machines, to minimize my usage of if statements, to tell rather than ask, to avoid casting and pointer arithmetic, to avoid code which transfers ownership of objects, to use std::string and std::vector rather than fixed-sized C-style buffers, to avoid premature optimization and premature abstraction, to prefer composition and aggregation over inheritence, to be careful to distinguish between a count of bytes or a count of characters, and the zillion other things which practicioners of TDD eventually stumble upon.
For me, TDD zealots are just one of a long line of religious loonies knocking on my door, trying to prove that my way of doing things is irrepairably broken and the only path to salvation is Jesus, Mohammed, Krishna, Dianetics, or Unit Testing. And maybe there’s a good idea or two to be gleaned from all the mountains of bullshit. But you know what? Keep your crazy religion, 'cause I don’t need it.
 - http://www.rtpspin.org/Information/030327prs.ppt
 - http://www.satisfice.com/blog/archives/27