Skip to content

Unit Testing: Short and Sweet

This is the short and sweet introduction to unit testing I always wanted to have as a reference for colleagues, friends, and family. Enjoy.

What Is a Unit Test?

A unit test ensures that an individual unit of code behaves as intended. A unit is a minimal chunk of code that can be tested in isolation, such as a function or a class.

A test is not a unit test if it talks to a database, requires network access, writes to the filesystem, or requires a complex environment to be setup. This is crucial to keep things independent, robust, and fast.

Unit tests form the basis of the test automation pyramid. Write lots of them. Make them run fast.

Why Unit Testing?

  1. Correctness: Unit testing helps you to write correct code. You detect errors early during development and avoid costly changes later on.
  2. Evolution: Unit tests allow you to evolve your code over time. You can refactor your code without fear of introducing subtle bugs. This is key for reducing technical debt and improving your design.
  3. Design: Unit testing encourages good design practices such as modularization and minimizing dependencies between components.
  4. Documentation: Unit tests document the behavior of the code. They serve as a form of executable specification.

Unit Testing Best Practices

Good unit tests follow FIRST principles:

Clean unit tests follow the AAA pattern:

This pattern implies testing a single concept per test case, using a single assertion.

Start with testing the happy path: Make sure that intended usage of the code produces the desired result.

Don’t forget the unhappy paths: Gracefully handle corner cases, unexpected input, pre-condition violations, or error conditions.

Aim to cover your complete public API with unit tests. Trivial functions like getters and setters might be excluded.

Use code coverage tools to analyze which code paths are actually triggered by your tests.

Let your testing code follow the same high standards as your production code: well designed, thoughtfully partitioned, and using meaningful names. Comments explain what is tested and why.

Refactor common setup code into a fixture to avoid repetition.

If your tests use tolerances, make them configurable so that you can check that nothing changed in the results.

Getting Started

Next time you…

  1. add new code, write at least one unit test covering the happy path
  2. find a bug, write a unit test that would have caught it
  3. refactor a part of your code, bring it under test first

When time and circumstances permit: Setup code coverage and bring all critical parts of your code under test.

The Bottom Line

Unit testing is like exercising: you know it’s good for you, but it can be tough to get started. It’s even more difficult to stick to it after the initial enthusiasm wears off. It’s an investment in the future of your code that pays off.

Further Reading

Other articles I’ve written on testing: