Top 12 Selected Unit Testing Best Practices

BY MARKUS SPRUNCK

Writing just another best practice list about unit testing is easy, but working according these recommendations is a more difficult task. In the project described in Library to Empirically Estimate Big-O Time Efficiency and Check Results of Analysis in JUnit Tests with Java 8 the following tips have been used. All the source code in this project has been developed with 100% TDD and applied most of the best practices. Just 'Use Parameterized Tests' and 'Structure All Test Cases' has not been applied, because it was not needed.

Always Write Isolated Test Cases

The order of execution has to be independent between test cases. This gives you the chance to rearrange the test cases in clusters (e.g. short-, long-running) and retest single test cases.

Test One Thing Only in One Test Case

Each test should focus on one aspect of an isolated method and/or class. For integration test this goal may be difficult to achieve, but also here trying to focus on single aspects is helping.

This means that you usually have just one assert per test case. More than one asserts are always a hit that your test doesn't focus on one aspect or functionality.

Use a Single Assert Method per Test Case

Don't test too many different things at once! If you use just one Assert it's easier. This increases the number of test cases and the single test better to maintain. If one or more tests fail, you may find the root cause in a easier way.

Use a Naming Convention for Test Cases

A clear naming convention like: <Method-Name Under Test>_<Scenario>_<Expected-Outcome>. This helps to avoid comments and increases the maintainability and in the case a test fails you know faster what functionality has been broken.

Use the Arrange-Act-Assert Style or Given-When-Then Style

Use separated blocks ("ARRANGE", "ACT" and "ASSERT") help to improve maintainability and use comments to mark these blocks. An alternative is the ("given", "when" and "then") style. This gives more structure to your unit tests.

Avoid the Expected Exception Tests

Maybe @Test(expected = ArithmeticException.class) doesn't test what it claims to test. Sometimes it happens that the exception is thrown some were else in your code (this happened to me some time ago).

Structure All Test Cases

Like Short-/Long-Running, Integration-/Unit-tests, but don't use test suits to control order of execution. When you have hundreds of test cases you don't like to wait several minutes till all tests are ready. Especially integration test may be slow, so separate them from the unit tests.

Use Descriptive Messages in Assert Methods

Describe the WHY and not the WHAT, not like Assert.assertEquals( a, b, "must be equal"). This helps to avoid to much comments in the test cases and increases the maintainability.

Measure Code Coverage to Find Missing Test Cases

Best indicator to find out what is not tested, but don't be to sure that the code works.

Don't Forget to Refactor the Test Code

Also maintain your test code (especially when after refactoring the code under test).

Limit Use of Mocks

In some cases absolutely necessary, but with better design stubs should be enough.

Use Parameterized Tests

They can help avoid code duplication and the best is the business gives you the data.