Prayer-Driven Development (PDD) -- the opposite of TDD
In the past few years (and even more so in the past few days), I've heard a few developers say things like "I haven't got started using automated testing yet" or "We tried doing testing, but it didn't work out" or "We did some tests once, but they fell out of date and now we just unload the 'test' project."
First, I must confess that I was one of those people not more than 2-3 years ago. I didn't 'get it'. I was doing it wrong, I admit completely. I understood the precepts and the reasoning, but it didn't resonate with me. I was too focused on "just getting done" which seemed more important at the time.
However, as time went on, the project grew more and more complex, functional testing became more and more complicated and tedious and changes to already-shipped codebases became an exercise in absolute terror (*fingers crossed* -- Please don't let this change cause a regression bug... *PLEASE*).
Arguments from Ignorance
All the arguments against TDD, that I've heard at least, boil down to these:
- Argument 1: It takes too long, our deadline will slip, I HAVE to ship ON THE DEADLINE!
- Argument 2: It's too hard, I hate having to leave the IDE to run some chumpy tool, I have to set up a database just for testing, Our environment isn't conducive to repeatable testing, etc, etc
- Argument 3: After having a decent suite of tests, one small change breaks tons of tests; I spend more time changing tests than changing the code.
I have used all of these arguments against myself and against others. All of them I have eventually come to find out are completely wrong and are 'Arguments of Ignorance.' These arguments were only true IN MY MIND because I was doing it wrong and I was proving my arguments correct. These weren't arguments against TDD, these were arguments against "Doing TDD incorrectly."
Knowing the Knowledge
I finally came to the conclusion that something was amiss and that ALL these people talking about all the benefits of TDD couldn't ALL be wrong (or just hippies with too much free time and no real-world experience). I kicked out my inner curmudgeon and replaced it with humility and decided I would go back to school and learn me some good practices!
Eventually I came to realize that TDD works best when the following criteria are met:
- Tests should be small, easy to write, and quick to run.
- Tests should be repeatable, independent, and self-documenting.
- Your tooling should be near frictionless -- constant, quick feedback is key
- Test should focus on establishing known facts, not mirrors of the code they're testing (brittle tests == little value)
Following these principles, testing became easy and even enjoyable. It challenged my understanding of the requirements placed before me. It challenged me to think of how my code could be used in other ways and with other intents. It challenged me to think about my design, and how certain design choices affected the code's independence from too many dependencies.
Practicing the Preaching
After spending time getting the hang of it and realizing all the benefits from doing TDD (which are well documented and shouldn't require any elaboration here -- please Google :) ), I started to doubt myself and my career as a developer. How come I hadn't been doing this all along? I claimed to be providing my customer the best I had, but I realized that I could never VERIFY the best I had. I would write code and then, essentially, hope for the best. I had NO WAY of PROVING my value to the customer. It was entirely subjective and I was, apparently, fine with that. I didn't know any better, but ignorance is no defense. I had an ETHICAL OBLIGATION to pursue excellence in my career and provide the maximum value for time and money my customer spent on me. I regret not having provided more value to customers. I regret not having taken the time to learn things that were easily within my grasp. I regret leaving untested and untestable codebases behind for other programmers to have to maintain and cringe and curse at. I regret not having given the extra performance and reliability boost that TDD afforded to my customers.
I have resolved now to not let that continue to happen and that I will continually attempt to stay on top of best practices and recent inventions in the world of software development (both inside and outside of the .NET world) so as to provide my customer with the best possible product for my time. Test-driven development is a repeatable, measurable way of accomplishing that while simultaneously providing another metric by which customers can gauge the value I provide them.
Go Forth
My son is in Cub Scouts and their motto is 'Do Your Best.' How can I look him in the eye and tell him how important that is if I am not doing the same for myself? I strongly urge you, fellow developers, to do your own research and re-evaluate your decision not to use TDD (or re-evaluate your existing TDD practices to make sure you're taking full advantage of the latest and greatest practices and tools). You owe it to your customers and you owe it to yourself to be the best you can be.