When I first heard about Test-Driven Development, I thought it was the strangest thing ever. But now, after having started actually learning and practicing TDD, I’m finding it to be incredible valuable in ways I don’t think I’d really be able to understand until I actually started coding. The benefit, one among many when it comes to TDD, is what I call the Whack-a-mole factor. Before I can get to that, let me briefly explain TDD.
When taking a TDD approach to writing code, you write code-based tests of features before to implementing the actual features. Here is an example of such a test, taken from the excellent online Ruby Tutorial at Pragmatic Studio:
What you’ve effectively written here is what is called an “executable spec.” In other words, it is a document that is both human- and computer-readable. Ok, so as far as the human readable aspect goes, you do need a bit of a programming background, but even if you have no programming knowledge whatsoever, you can still read the header block, such as “saves the movie and shows the movie’s details.”
Then, after having written the actual feature, you test the feature using the above spec and it will either pass or you’ll get one or more errors. Now, you may be wondering, why would you want to spend time writing one piece of code to test another set of code? Doesn’t that seem like doing the same thing twice?
Well, this is where the Whack-A-Mole scenario comes in. Imagine this scenario: you’re humming away, implementing one feature after another. Then, at some point, when completing the implementation of feature 55, suddenly features 10 and 11 break. In other words, something you did when working in one part of your code repository had an impact on some completely different feature that you didn’t even touch. Then, when working on feature 56, features 21, 28, 32 break. If you were not taking a test-driven approach, you have to spend a ton of time trying to go back and check those features you worked on way back when, and probably have forgotten half the details about them and try to see how your current work ended up breaking them. It’s an unending, very wasteful, very aggravating game of Whack-A-Mole.
Coding without writing automated tests ends up being a never-ending game of Whack-A-Mole bugs that keep popping up in old features you thought you were done with. (Photo Credit: zdnet)
The more tests you write, the more valuable your suite of tests becomes
If you had take a Test-Driven approach, this would not have happened, because you’d be constantly running automated tests to, among other things ensure that you’re not breaking other parts of the system unintentionally. TDD isn’t fool-proof in this regard, ie you can still unintentionally break stuff, but it can radically reduce the chance of it happening, because your automated test suite is continually checking for failures not just of the current feature you are working on, but of all features that have been created up to that point (assuming, of course, you’ve written tests for each of them.) And that is a very big deal.
Maybe more importantly, it wasn’t something I didn’t understand about TDD until I started coding and decided to forego writing tests to save time, only to discover moles popping up left and right, finding myself fixing stuff that I didn’t even know I was breaking.
In other words, even though coding a test before writing the actual feature may seem weird and inefficient, it can become a huge time- and sanity-saver in the long term.
There are lots of and lots of other benefits to TDD, such as forcing you to think through what it is you are actually going to build before building it, but the [bonk the heads] value is one that I rarely see mentioned, and didn’t really realize until I started doing TDD myself.