Writing good documentation is hard.
Test writing enthusiasts like to point at their suites of tests and call them the “living documentation” of the system. But reading tests is a terrible way of trying to understand the behaviour of a system. Usually written in the same programming language as the system, they're difficult to decode and don't answer the fundamental questions that documentation should answer for the reader
- How does it work?
- What can it do for me?
- How can I make it do that?
Simple JUnit tests are terrible documentation that is, unless you follow a few simple rules...
Use the Test class name suffix convention
To name a test class, take the name of the class under test and add “Test” on the end.
e.g. MovieTitleMatcherTest
contains tests for MovieTitleMatcher
This instantly adds context to the tests, connecting them to where the behaviour is implemented. So for any given class, it's easy to find the tests that verify it's behaviour and vice versa.
Integration and system tests can also be named after similar higher-level prod-code abstractions (MegaMovieMarket
will have it's behaviour tested and documented by MegaMovieMarketTest
) in fact, the lack of a viable candidate to attach this kind of test class to, might indicate that a key abstraction is missing.
Write test names as natural language sentences
Ask yourself how you would describe the behaviour being tested to someone simply and succinctly. Chances are, that sentence would make a good test name. Use natural language with an active voice.
public class MegaMovieMarketTest { @Test public void findsMovies() @Test public void sellsMovies() @Test public void buysMovies() } public class MovieFinderTest { @Test public void findsMoviesByPartialTitle() @Test public void findsNoMoviesWhenNoMovieTitleContainsThePartialTitle() @Test public void findsMoviesReleasedWithinAGivenSpanOfYears() @Test public void findsNoMoviesWhenNoneWereReleasedWithinAGivenSpanOfYears() } public class MovieTitleMatcherTest { @Test public void matchesMoviesWithTitlesContainingTheSearchText() @Test public void isFalseOtherwise() }
If you spend most of the day diving in code, the simple sentences are easy to decrypt.
“Movie title matcher, matches movies with titles containing the search text”
For non-developers, explicitly expanding the camel casing into sentences and removing the surrounding programming language noise makes everything a little easier to parse..
Mega Movie Market Finds Movies Sells Movies Buys Movies Movie Finder Finds movies by partial title Finds no movies when no movie title contains the partial title Finds movies released within a given span of years Finds no movies when none were released within a given span of years Movie Title Matcher Matches movies with titles containing the search text Is false otherwise
Here we have perfectly readable summaries of each unit's behaviour written in a natural language that we can show to testers, support and business analysts.
In fact, the Enso IntelliJ plugin displays a live view of exactly this.
Select quality relevant examples
A common trap developers fall into when writing tests is to think of it as an opportunity to demonstrate how many different combinations and permutations (whether informative or not) they can think up.
It's almost as if more tests == better system
They go for quantity over quality even though a better example or a small change in wording would convey the same amount of information. No one likes to read long lists masquerading as documentation and tests that describe application features are no exception.
Save the reader from having to wade through the superfluous noise. Think of every test you write as a key fact you really need the reader to know about. The more tests you need to describe what a unit does, the more work you force the reader to do to understand what it does, and that's even before they decide if they want to use it.
Don't be afraid of using long descriptive sentences when necessary but also be careful when you find yourself writing them. Ask yourself whether you really need so many words to communicate the purpose of the test.
Tests can be documentation
Writing good documentation is hard but even the humble JUnit test suite can go some way towards becoming “living documentation” by following a few straightforward rules to produce easy-to-read summaries of class, component and application behaviour.
Summaries that you might even be able to give to your stakeholders as evidence that your system does what you say it does.