It is at that point that developers
are forced to make a tough decision: dedicate precious time to
improving their tests or ignore the problem, effectively throwing away
their hard work. The cause of this problem is simply inexperience
writing unit tests.
In this article, I'll try to bring you some
of the most important practices I've learned over the years while
developing and consulting, and while training developers. These tips
should help you write effective, maintainable, and robust unit tests.
And I hope this advice helps you to avoid huge amounts of wasted time
and effort.
The Truth About Unit Testing
In
this section I'll outline some of the most common beliefs about the
benefits to be gained by using many unit tests and explain why these
beliefs are not always necessarily true. And then I'll help you make
these beliefs hold true for your projects.
Tracking Bugs is Easier
Well, not necessarily. How do you know that your tests are correct?
That they fail when something actually breaks down? How do you know
that you're covering enough code in your tests to ensure that if
anything is wrong in your production code, that some test, somewhere,
will break?
What
happens if you have bugs in your unit tests? You'll suddenly start
getting a lot of false positives—essentially, a bug will be found, but
the problem won't be in your code under test. Your test's logic has a
bug and therefore the test fails. These bugs are the most annoying and
hardest to find because you're usually looking in the wrong place,
checking your application instead of checking your tests. In Section I,
I'll show you how to ensure that having a lot of unit tests does in
fact make tracking bugs easier.
Code is Easier to Maintain
Considering the last point, you're probably inclined to think this
belief isn't necessarily true either. And you're right. Let's say that
for each logical method in your code you have at least one test method.
(Realistically, you'll probably have even more.) In projects with good
test coverage, as much as 60 percent of the code can be unit tests. Now
consider that the tests have to be maintained as well. What happens if
you have 20 tests against a complex logical method and you add a
parameter to the method? The tests won't compile. The same thing
happens when you change constructors of classes. Suddenly you find
yourself needing to change a lot of tests just to make sure your
application still works. And that takes lots of time.
For
this belief to be true, you need to make sure your tests are easy to
maintain. Write them while keeping the DRY rule in mind: Don't Repeat
Yourself. I'll look at this issue more closely later.
Code is More Understandable
This is a benefit of unit tests that people don't usually expect at
first. Think about changing code (say, a specific class or a method) in
a project you've never seen before. How do you approach the code? You
probably go around all the project code looking for places where this
specific class or method is being used. Not surprisingly, unit tests
are a great place to find such examples. And, when written correctly,
unit tests can provide a handy set of API documentation for the
project, easing the process of documenting and understanding code
behavior written by old and new developers on the team.
However,
this is only true if the tests are readable and understandable, a rule
that many unit test developers don't follow. I'll expand on this
belief, and show you how to write readable unit tests in the Readable
Tests section of this article