Motley says: "I can't write tests before application code - there's nothing to test."
Motley: You can't possibly write tests before code - there's nothing to test.
Maven: Writing tests for a method before coding it has all kinds of design advantages.
[Context: Motley has been writing unit tests for a week. Maven wants to take the next step]
Maven: Hey. Looks like you're getting pretty good at this unit testing thing.
Motley: Yeah, I can definitely see the benefits of having a thorough suite of tests. I can make sure that with every code change I don't break anything.
Maven: Want to take it even farther? Do you want to make an even bigger difference in quality?
Motley: You really are a poop disturber, Maven. Fine. Let me hear about your hair-brained scheme.
Maven: How about this? Try writing your tests first before you write your code. It's called test-driven development, or TDD for short.
Motley: I can't write tests before I write any code! There would be nothing to test! You've been sniffing to much glue for your own good.
Maven: No, I am serious. Thinking about how you are going to test your code before you write it has all kinds of advantages, including driving your design. In fact, TDD is more of a design technique than a test technique when you really think about it.
Motley: So how could this possibly drive my design? What difference would it make if I write my tests before my code - which still seems crazy to me - or after? It's like saying that I should edit my book before I write it.
Maven: Maybe if you thought more carefully about how your book was to be edited, you'd do a better job writing the book the first time. With TDD, since you write your tests first, your design automatically is testable, which the test team will love. You can also view your APIs from the perspective of a client even before the API is implemented, so you know right up front whether the API is usable. In addition, coupling and cohesion problems in your code come to light immediately. I am sure you hate programming to difficult APIs. Well, this way you make sure that your APIs are clean before you start because you are using them. TDD essentially forces a good design to emerge based on your tests.
Motley: I'm still not sure about this. So all I have to do is write my tests before the code?
Maven: Well, to truly do TDD, here are the steps to follow:
- Start with a requirement. A requirement could be one method you want to implement.
- Write a test for that requirement.
- Write just enough stub code to make the test and code compile.
- Write just enough code to fail the test.
- Execute your tests and watch them fail.
- Write just enough code to pass the test.
- Execute your tests and watch them pass.
- Execute your tests to ensure you have not broken anything.
- Go to step 1.
Motley: That's a lot of steps. Seems too complicated to really be useful. And what's the point of writing a failing test first?
Maven: Actually, it's not complicated. Once you get in the groove, it actually feels quite natural. Oh, and the point of writing a failing test is essentially to test your test. If you write a test and expect it to fail but it passes, you know you have a problem with either your test or your code. By starting with a failing case and then watching it pass, you are more confident that your test is good.
Motley: Let me finish what I am doing with my current set of modules and then maybe I'll give this a shot. No promises. You'll also have to enlighten me a bit on the refactoring step, as I'm not sure what to do there.
Maven: No problem, Motley. I applaud you for having an open mind to try this stuff out.
Motley: Whatever. The boss says you were hired for your sound engineering ideas, so I guess I should humor him and listen. Hehehe. Kidding, of course. Maybe.
Maven: Stay tuned. I have a lot more to say about TDD. It's a great developer technique.
Motley: Can't wait. Ugh.
Maven's Pointer: A precursor to effectively doing test-driven development is understanding how to write good unit tests. Use a proven test framework to make it easy to write tests, and ensure your tests execute quickly. After all, with TDD, you are perpetually running your tests. It's such a great way to develop code that I don't think I'll ever go back to writing tests after code.
Maven's Resources: Test Driven Development: By Example, by Kent Beck, Addison-Wesley, ISBN: 0321146530, 2002.