Unit tests are not for validation

A common, but mistaken view of unit tests is that their main function is to validate code. One of the most common arguments used against the practice is that you can’t prove your code works with unit tests. This is of course a truism of all testing, not just unit tests, but I believe also reflects a misunderstanding of the real advantages provided by unit testing: behavior stability.

The advantage of unit testing comes not when you run your tests, see a green light, and assume you’ve written the right thing. This is actually a rather silly assumption to make, and if you run into a developer that assumes green light means “it works” you should correct them at the earliest opportunity. The great advantage of unit testing comes when you want to change the code without changing behavior.

Why would you ever bother to change code without changing behavior though? Shouldn’t you leave code alone unless you intend to fix a bug or add a feature?

Yes. You should leave code alone unless you intend to alter its behavior. This doesn’t mean though that the only reason to change code is to change behavior. More often than not, when you need to change behavior you’ll find that the architecture doesn’t readily support it as is. In the quest to add a feature or fix a bug you may find that you need to alter the structure of a component or components. This is called refactoring and it is here that unit testing really lends a hand because it allows you to restructure your program and be fairly sure that you’re not altering behavior–at least nothing the original author intended.

Furthermore, even if you don’t restructure the program to fix a bug or add a feature, you still don’t want to change things in ways the rest of the program doesn’t expect and possibly cannot handle. Fixing bugs can very often introduce other bugs, and adding features can quite often break existing behavior. If you don’t have unit tests you can’t check these things until your product is in QA, which in some firms doesn’t happen right away and is certainly less speedy a feedback than running tests before you ever even check anything in.

So that is how you should think about unit tests. Don’t think of them as validators checking that your code is doing the right thing. Think of them as a method to document what your code does in such a way that anyone can check that it continues to do the same thing after it’s changed.


4 comments on “Unit tests are not for validation

  1. Tim K says:

    Thanks for clarification 🙂

  2. RC says:

    Good perspective. I would go even further and say that you should only test behavior that is unlikely to change. Testing should speed up development by giving you a quick check that your new code didn’t break anything. If you have to re-write tests because behavior changed or a feature is added, that slows you down.

    • Crazy Eddie says:

      I can’t agree with that. It sounds too much like writing tests after the fact and this is certainly the hard way to go about ensuring coverage is adequate.

      Keep your objects simple and tests don’t get all that complicated. Implement complex behavior with many small, simple objects.

  3. Joker_vD says:

    But of course. (Unit) tests prove existence of bugs and errors. To prove their absence, formal verification methods (and, in particularly, type checkers) were invented. Sadly, we bump into problems with undecidability pretty quickly there.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s