After having applied TDD for several years now, and after having assumed my colleagues do the same, I have been surprised lately to hear how many developers write their tests after their code. Test-driven development is meant to be:
- Write a test
- See that it fails (and fails correctly)
- Write your code
- See that your test passes
- Refactor (and see that your test and all others still pass)
This has led to the well-known (for some) red-green-refactor adage. If you write your test first (assuming you have the necessary class and method to hook into, but without implementation), it will fail of course (red). Then you implement that empty method until your test passes (green). And finally you can check if you can write this working code a little prettier, more concise, etc.
Rather than shout that people have to write their tests first because I say so, I would like to point out the advantages of writing tests first:
- it forces you to think about the public interface
- it will help in keeping the implementation small and simple
- if you have too many outgoing calls, you might find that you have to do an awful lot of setup work before your test passes. Maybe you should extract some parts to other classes and/or methods
- it forces you to think about the correct outcome first
- writing code afterwards will push you into the direction of writing a test as a function of the code you just wrote, not as a function of what the code should actually do
- you won’t have any more code in your test than necessary
In some bad cases, I’ve seen people commit their changes to the central repository with failing tests. "I’m busy fixing it," they say. OK, no problem if this happens once. But it can hinder the other developers, and can lead to sloppy coding, where a whole range of tests fail and people lose track of which really fail and which are being fixed. Worst case scenario: failing tests remain unfixed.
I know sometimes you start out implementing a feature because you’re thinking while you code. But try it out. Force yourself to write your tests first. Start by simply instantiating the class you need and calling the method you want to test. Then slowly start adding the bits you need, switching back and forth between your test and the class you’re testing.
Several (good) developers have looked at me strangely when I said "yes, I really do write my test first". But after a while, it doesn’t feel so weird anymore. On the contrary, flying head-first in the code and writing your tests afterwards will feel dirty.