repost of my blog entry of 2003, April 08:
This is a dialog I created in July 2002, from messages on the Test Driven Development mailing list -- an email conversation between Robert Blum and Roger Lipscombe. After my editing, they didn't recognize their words, so perhaps I did a little more writing than editing. Any similarity to my favorite comics characters is purely coincidence.
Calvin: I don't do test driven programming. I write some code, and test it manually, walking through it in the debugger, checking that it works.
Hobbes: How do you know that it works? Could you express that as a test before you run your code?
Calvin: I can't think about the test until I've thought about the code
Hobbes: Changing the habit of writing code before the test can be a bother. Try this: Write the code on paper. Then write a test.
Calvin: Paper?!
Hobbes: What if you just outlined the code on a whiteboard and didn't write any real code? Could you still write a test first?
Calvin: I'd feel silly doing that alone.
Hobbes: What if you explained it to your pair partner? Could you still write a test first, or maybe have your pair partner write the test?
Calvin: That could work.
Hobbes: I notice you're refactoring without tests. What's that like?
Calvin: After I refactor, I have to test it again manually, in case I make a mistake doing the refactoring.
Hobbes: Wouldn't it be easier to run some quick automated tests before and after you refactor?
Calvin: Well duh! If I had the tests.
Hobbes: If you do test-driven development, your tests drive the design of your code, and as a side-benefit, you get a nice small set of automated tests that make refactoring safe.
Calvin: Perhaps if I start by thinking about the interfaces that my class or module would need to support, I would be able to write the unit test first? Does this sound like the kind of thing I should be trying more of?
Hobbes: I think so. If I were given just the task of writing a class or module, my first test would describe a very simple case of what I wanted from that code. The interface of this not-yet-written code is evolving, of course, during my test-driven development process. Since I'm calling the functions that I need at each moment, without a care how (or if) they are implemented, it tends to create a pretty useable interface.
Calvin: So you find out quickly if your interface functions are no good when you're forced to use them as client, in the tests, before investing a lot of work at writing them!
Hobbes: Now you're getting it.
Calvin: Tell me, when you think of a feature, is your next thought about testing or implementation?
Hobbes: I just think about using that feature. Which leads me to an example of how I would use it. Now I just write down the results I expect from that, and voila, there's the test. I'm not even actively thinking 'I have to write a test now. How can I test it?'. My main focus is how I can use it.
J. B. Rainsberger added a few more lines:
Hobbes: Have you written tests for that code yet?
Calvin: Tests?! TESTS?! I don't need tests! What do I need tests for? Don't you think I can write something this simple without using tests as a crutch?! I know it's right!
Hobbes: (rolling his eyes) Of course you do.
Calvin: Right. Now help me fix these last four bugs.
And Laurent Bossavit capped it off:
Hobbes: I thought I was doing that.