- Introduction
- Test-Driven Development
- Incremental Test-Driven Development
- The Payoff for Test-Driven Development
- Learning to Write Good Unit Tests
The Payoff for Test-Driven Development
An obvious objection to test-driven development is that writing all of these tests takes time that could be used to write more production code. Yes, it does, no argument there. It takes a lot of time to think up useful test cases and to implement all of the assertions in the unit tests. But that's not the whole story. Writing the code has never been the limiting factor on projects. (If it was, programmers would be sent to "touch typing" courses.) The benefits of test-driven development show up in how the rest of the software development activities are improved. The time taken to produce quality applications is reduced by the following factors:
Much less time spent debugging mistakes in the code. Life is just too short to spend time stepping through the code line by line in a debugger to see what's going wrong in the code. Although I have in the dim and distant past spent lots of hours stepping through assembler code in a debugger, since adopting test-driven development I've only ever used a debugger for teaching purposes. In fact, I don't think I've ever used the Ruby debugger. (But if you really want to try, just start Ruby with the command ruby -r debug tc_CircularCounter.rb and then enter help at the prompt to see the commands that are available.)
Less time trying to locate mistakes. There is no need to search all over the source; you know where to start lookingin the method you're currently working on. Yes, you might find that one of your "tested" methods is actually incorrect, but most of the time the mistake is going to be in the method you're working on.
Fewer mistakes getting through to functional and acceptance testing. By building up the unit test as you go along, test-driven development helps catch more mistakes while the methods are being written. This is great news because it means there are fewer mistakes for the testers to catch, which in turn means that there are fewer mistakes for you to find and fix when everyone is asking "Why haven't you finished? You said you were nearly done a week ago!"
Documentation on how to actually use a class. This advantage is slightly counter-intuitive, but I've lost count of the number of times I've looked at the test cases to see how to use a method. The set_up method is a great place to find out how to create the objects, and then the test_xxx methods are a great way to see how to use the various methods. The great thing about using tests as documentation is that you know the example code works because you can run the tests successfully.
More confidence that changes in one place haven't broken something else. Programmers are a suspicious lot. Many have justifiable fears that making a change to one aspect of a design will break code in other parts of the application, so changing working code is always viewed with trepidation. Test-driven development reduces these fears because after every small change you can rerun the entire suite of unit tests to make sure that you haven't broken something else. It's also really useful for when upgrades come alongupgrading is less stressful when the unit tests give you confidence that the application still works.
A reasonable quality level in applications without imposing a heavyweight process on developers. Although remembering to always write the unit tests first can be difficult, it's a lot easier to stick with test-driven development than it is to use any heavyweight process. Design and core reviews are very effective at improving the quality of an application, but it's very easy to slack off on the reviews. Many teams find that although they're supposed to do reviews, in practice it only happens for some small fraction of the code. In contrast, with test-driven development you're less likely to slack off because the benefits are so immediate.