by mlepage » Aug 29, 2003 @ 9:37pm
Let me go on about test code while I'm here and waiting for dinner.
The first complaint I usually hear about test code is that it tells you when something goes wrong, but not what is going wrong or exactly where it is going wrong. The mistaken belief is that you need to use the debugger to discover all of that.
These mistaken beliefs are rooted in misuse of test code as well as misuse of the debugger.
Proper test code is written to test each level of the hierarchical structure of your program. So when it fails, you know where the failure is. Sure, if a high level component fails, the failure might be there or in a lower level component. But if you are also testing the lower level components individually, you'll have already answered that question.
Proper test code is written *while* you write your actual code, or even *before* you write your actual code. A lot of people understand that having test code is handy to test the *implementation* of your code for correctness as you write it. But even more important is having test code to test the *interface* of your code before you write it. In that respect, think of test code as something that happens almost in the design stage of development, as well as the implementation stage.
If you've managed to get to the debugging stage without writing test code, of course diving into the debugger seems a better option. But that's only because you've skipped the whole step of writing your test code, which should have happened before. If you'd written your test code diligently, you wouldn't be in this quandry of being forced to use the debugger even when it isn't necessarily the most efficient way to debug your problems.
Now, let me caveat all I've just said. Firstly, I find there tends to be a bit of a cost/benefit judgement to whether I write test code for a module, and how much I test code I do write. If it's an important module, or it is complicated, or I've never done that type of code before, or I intend to refactor it, then I will lean towards more test code with deeper and broader coverage. On the other hand, some modules I write have little or no test code.
Like so many decisions in software development, it's a judgement call, but I consider it to be the mark of an inexperienced or amateur developer to be so inclined as to have little or no test code at all.
Secondly, there are cases where it makes sense to approach a problem using the debugger as your primary debugging tool. It's just that this isn't always the case. And it's a good practice, once you've discovered the problem, to write test code to ensure it doesn't happen again, or that similar problems (perhaps even in similar modules) are flushed out.
Consider it. You've just went into the debugger to look at a module. You don't really know what the problem is, but you have a hunch it's there. What does that say about your development practices? Why didn't your test code for that module reveal the problem? (Fix the test code.) Don't you have test code for that module? (Write the test code!)
I'm only coming down hard on the debugger here because I see it misused often in development shops. Don't get into the habit.
Anyways, Kernighan and Plauger have a whole chapter on debugging in the book I mentioned, and the debugger is only one aspect of debugging. It needn't dominate your development practices. There is also a chapter on testing. I reviewed the book here: