What is unit testing?

Unit testing is, roughly speaking, testing bits of your code in isolation with test code. The immediate advantages that come to mind are:

  • Running the tests becomes automate-able and repeatable
  • You can test at a much more granular level than point-and-click testing via a GUI

Note that if your test code writes to a file, opens a database connection or does something over the network, it's more appropriately categorized as an integration test. Integration tests are a good thing, but should not be confused with unit tests. Unit test code should be short, sweet and quick to execute.

Another way to look at unit testing is that you write the tests first. This is known as Test-Driven Development (TDD for short). TDD brings additional advantages:

  • You don't write speculative "I might need this in the future" code -- just enough to make the tests pass
  • The code you've written is always covered by tests
  • By writing the test first, you're forced into thinking about how you want to call the code, which usually improves the design of the code in the long run.

If you're not doing unit testing now, I recommend you get started on it. Get a good book, practically any xUnit-book will do because the concepts are very much transferable between them.

Sometimes writing unit tests can be painful. When it gets that way, try to find someone to help you, and resist the temptation to "just write the damn code". Unit testing is a lot like washing the dishes. It's not always pleasant, but it keeps your metaphorical kitchen clean, and you really want it to be clean. :)


Edit: One misconception comes to mind, although I'm not sure if it's so common. I've heard a project manager say that unit tests made the team write all the code twice. If it looks and feels that way, well, you're doing it wrong. Not only does writing the tests usually speed up development, but it also gives you a convenient "now I'm done" indicator that you wouldn't have otherwise.


The main difference of unit testing, as opposed to "just opening a new project and test this specific code" is that it's automated, thus repeatable.

If you test your code manually, it may convince you that the code is working perfectly - in its current state. But what about a week later, when you made a slight modification in it? Are you willing to retest it again by hand whenever anything changes in your code? Most probably not :-(

But if you can run your tests anytime, with a single click, exactly the same way, within a few seconds, then they will show you immediately whenever something is broken. And if you also integrate the unit tests into your automated build process, they will alert you to bugs even in cases where a seemingly completely unrelated change broke something in a distant part of the codebase - when it would not even occur to you that there is a need to retest that particular functionality.

This is the main advantage of unit tests over hand testing. But wait, there is more:

  • unit tests shorten the development feedback loop dramatically: with a separate testing department it may take weeks for you to know that there is a bug in your code, by which time you have already forgotten much of the context, thus it may take you hours to find and fix the bug; OTOH with unit tests, the feedback cycle is measured in seconds, and the bug fix process is typically along the lines of an "oh sh*t, I forgot to check for that condition here" :-)
  • unit tests effectively document (your understanding of) the behaviour of your code
  • unit testing forces you to reevaluate your design choices, which results in simpler, cleaner design

Unit testing frameworks, in turn, make it easy for you to write and run your tests.


I don't disagree with Dan (although a better choice may just be not to answer)...but...

Unit testing is the process of writing code to test the behavior and functionality of your system.

Obviously tests improve the quality of your code, but that's just a superficial benefit of unit testing. The real benefits are to:

  1. Make it easier to change the technical implementation while making sure you don't change the behavior (refactoring). Properly unit tested code can be aggressively refactored/cleaned up with little chance of breaking anything without noticing it.
  2. Give developers confidence when adding behavior or making fixes.
  3. Document your code
  4. Indicate areas of your code that are tightly coupled. It's hard to unit test code that's tightly coupled
  5. Provide a means to use your API and look for difficulties early on
  6. Indicates methods and classes that aren't very cohesive

You should unit test because its in your interest to deliver a maintainable and quality product to your client.

I'd suggest you use it for any system, or part of a system, which models real-world behavior. In other words, it's particularly well suited for enterprise development. I would not use it for throw-away/utility programs. I would not use it for parts of a system that are problematic to test (UI is a common example, but that isn't always the case)

The greatest pitfall is that developers test too large a unit, or they consider a method a unit. This is particularly true if you don't understand Inversion of Control - in which case your unit tests will always turn into end-to-end integration testing. Unit test should test individual behaviors - and most methods have many behaviors.

The greatest misconception is that programmers shouldn't test. Only bad or lazy programmers believe that. Should the guy building your roof not test it? Should the doctor replacing a heart valve not test the new valve? Only a programmer can test that his code does what he intended it to do (QA can test edge cases - how code behaves when it's told to do things the programmer didn't intend, and the client can do acceptance test - does the code do what what the client paid for it to do)

Tags:

Unit Testing