Test Driven Development (TDD) is an interesting concept. In many places the primary artifact of TDD, the unit test, has been used as an excuse to not have a test group/department. After all, if the unit tests pass, then the system has to work right?
Maybe. For a simple program or library that might be the case. But as systems get more complex that is less and less true. Because the behavior of the system is more than the behavior of the parts, and you can’t test system behavior by testing the parts. Integration tests help, but they’re not unit tests, and they’re not a complete substitute for trying the real thing in the real world.
To me, what TDD is good for is Design by Example. Write your example/demo code, then write the code to make it work. Unfortunately, that’s kind of counter to our usual process. Figure out what’s needed. Write a justification. Write a design doc. Write a detailed design doc. Write some code. Write some tests.
So here’s a quick way from Kent Beck, the father of TDD, to try out TDD, without having to change the entire system. In fact. it probably won’t take any longer than it would have anyway. You’ll end up learning about TDD, and probably end up with cleaner code.
- Change the code as usual
- Write a test that only passes after the change
- Revert to before 1
- Type the test again (copy/paste is cheating & invalidates the warranty of the exercise)
- Make it compile by changing the code
- See it fail
- Change the code to make it pass
The only thing I’d ask is that you do this as soon as you have the test(s) passing, instead of after you do your pre-commit cleanup/refactoring pass.
I bet you’ll find that the test you write the second time doesn’t look exactly like the test you did the first time. Because now you know how you really want to work. You have a better understanding of the usage of the code, and what the inputs and outputs should be.
So the change in the test drives a change in the design of the code. And the design change means that the code under test looks even less like the original than the test does. But that’s a good thing. Because the code now better embodies the intent. Instead of having the API reflect the underlying code, you’re incentivized (by the test) to make the code match the usage.
Which means your users will have fewer surprises and more joy. Which is always a good thing.