So, if you’re lucky, you’ve mostly missed another Internet pile-up about unit tests and so on, this one started by Joel Spolsky and some comments he made on his podcast.
I’ve already written a little bit about what Joel said, and I don’t want to rehash that. But I have seen a recurring theme in arguments that testing is overrated — namely that the testing that those people are writing about doesn’t seem to be related to the testing that I actually do.
I’m going to put the summary up front:
- “Unit Testing” and “Test Driven Development” are not identical concepts
- It would seem, on the available evidence, that those of use who are TDD or BDD backers haven’t done a great job of explaining this.
- TDD has code quality benefits that are completely separate from whatever function it has as a code verification engine.
- It would seem, on the available evidence, that those of use who are TDD or BDD backers have done a really poor job of explaining this.
In my head, Test Driven Development is a process where you write a short little test, write a short little bit of code to pass the test, refactor and move on. There’s constant feedback between code and tests, and you move between the two freely.
This is probably an over-generalization, but it seems like “Unit Testing” often refers to a process where you write a lot of code — days or weeks worth — then go back and try to write tests against it. That does sound painful. You can never quite remember what the code was supposed to do, and retrofitting tests to existing code is never fun. If that was the only kind of testing I was familiar with, and some yahoo came around shouting about how I needed to test 100% of the time, I’d probably think that guy was crazy.
Luckily, that’s not the way I test or the reason I test.
Put plainly, I write code test first because I write better code. And I write it faster. And when there are bugs, I find them quicker. And I enjoy coding more. Your milage may, of course, vary, but my milage from TDD is consistently good.
I write better code: Code written using TDD has a very distinctive style and structure. Smaller methods, smaller classes, very strongly decomposed, not a lot of duplication, not a lot of side effects. Mostly, this is due to the way in which small methods that do one thing are easy to test — the small structure evolves organically from the co-existence of the tests.
I write code faster: Here’s an idealized thought experiment. Let’s say I’m writing a browser feature, and it takes, say, 30 seconds for me to exercise the feature in the app. Let’s say it takes a full minute to write the initial test, but only a few seconds to run the test once it’s written. How many times do I have to check what I’ve written before the test pays for itself? Plus, the test is always there when I need to come back to the feature.
I find bugs faster: Even granted that TDD doesn’t catch all possible bugs, my experience in TDD-developed systems is that bugs are easier to find and fix, largely as a result of the smaller, less duplicated structure. Generally, the bugs are more localized
I enjoy coding more: Because it feels like a game. But hey, that’s just me, right?
I leave you with this Rails testing Haiku, courtesy of Pathfinder’s own Alice Toth:
flowing dots on screen
unbroken but for an F
my work is not done
Feel free to leave your own testing Haiku, or anything else, in the comments.


I think that you made the point!
Is important to why to do some pratice, to think about and be a philosopher, not just do it because everybody is talking about or because it’s a hype.
There are good reasons to test and think that its essecial to develop a good software but TDD is another think, and its not just about tests, but with no tests there are no TDD.
When you talk about a test taking only a few seconds, I assume you’re running spec_server?
Your points about faster coding and finding bugs faster are very valid. Many people seem to think TDD as something extra you have do, when in fact TDD makes the development faster because of the faster turnaround when developing/debugging.