FIRST Principles of Unit Testing

There are a few key principles that will help you write more effective unit tests. The FIRST acronym is a hand way to remember them.

Fast

A suite of unit tests should provide very quick feedback as to the success or failure. It’s important that Developers are not put off running the tests because they take took long. Ideally the whole suite should run in milliseconds (or seconds), but not minutes. The value, certainly for TDD is to get near instant feedback on changes as early in the process as possible.

Independant

Unit tests should be isolated from each other, one test should not depend on the outcome of another test. This will make the tests more robust, and failures you know are genuine and not because of a failure elsewhere. Unit tests should also be isolated from external systems such as the file system (although in som cases it maybe useful, just take care) or external services / 3rd party librarys. External components should be mock (and ideally abstracted behind an interface).

Test the smallest unit you can in isolation and set up each test using the 3 A’s

  • Arrange
  • Act
  • Assert

Each test should arrange the test data, act on the class under test, and assert the results.

Repeatable

It should be possible to re-run the tests with the same result every time. No dependencies on environment/time or external systems. This also includes data i.e no random data and clear down test data from previous runs to start clean each time. Tests using random data may intermittently fail, it will be hard and frustrating to identify and reproduce the errors. Ensure there are enough stable test cases for all the scenarios required.

Self-Validating

Tests should provide a simple pass or fail result. It should be obvious without any external or manual input as to the result of the tests. This will give quick feedback during development, any breaking changes introduced can be easily identified by running the test suite.

Timely

Tests should be written at the same time as the production code. TDD states that tests are written before the production code, but even without using TDD it is beneficial to write test code as close as possible time-wise to production code. 
Chasing test coverage months or years later seldom produces good quality test code, in some cases they are so heavily mocked that they add little or no value and could actually be a detrimental.