JUnit test names tips

November 7, 2019 - 4 minute read -
java testing tip naming junit

They say that naming is one of the hardest problems in software engineering. Well, perhaps. It’s at least one of the most common hurdles we need to clear.

The naming of test methods might not have the same potential for disaster as naming public APIs, but if you’re a developer who’s been thrown into an existing codebase, having good test names can help you make sense of things and when your tests fail, they can help direct your next steps.

Pick a core naming convention

For JUnit units tests, I typically use the following test naming convention:

<method>_<expected-behaviour>_<conditions>

There’s a few different conventions out there and there is merit in looking at some alternatives. My advice is not so much about this convention but about getting the most out of whatever convention you choose to adopt.

Tips

Let’s have a look at some potential misuses of this convention and how we can make them better!

Class under test

Let’s imagine we want to unit test this ArticleStore class:

class ArticleStore {
    private ArticleFetcher fetcher;

    void store(Article article) { }
    Article getArticle(String articleId) { }
    List<Article> getArticles() { }
    List<Article> fetchArticles() { }
}

The implementation details don’t really matter too much, so I’ve left them out.

Be Accurate

I’ll start by staying that at the very least your test name should be factually correct. If you’re in a hurry and copying and pasting tests around, you might neglect to change a clause in the test name, making it inconsistent with what the test is actually doing. Don’t do that. Take the time to read your test names and their implemetation.

Be Informative

getArticle_shouldReturnCorrectValue_whenGivenArticleId

In this case the “should” clause doesn’t add any value. It’s a test, of course we want to verify that it returns the correct value. That’s the entire point of having a test!

To be more informative, we should describe what the correct value is.

Suggestion: getArticle_shouldReturnStoredArticle_whenGivenArticleId

Focus on the unit

getArticles_shouldReturnAllArticles_whenArticlesSynced

For unit tests, the test names should remain relevant to the unit under test. It’s tempting to include context that hint how the unit is used in practice, but these can often get out of date or just be confusing to someone without a full picture of the system behaviour.

In this case, we shouldn’t mention that the articles have been synced into the store, because the class under test doesn’t support syncing only storing. It may be true that in our app, where the articles are synced into the store, but it’s not true of the ArticleStore in isolation.

Save that extra context for your integration tests.

Suggestion: getArticles_shouldReturnAllArticles_whenArticlesStored

Keep your terminology consistent

Similarly; avoid using synonyms for important terminology or actions. If you class defines that you “store” Articles, then don’t refer to them as being “added”

So rather than: getArticles_shouldReturnAllArticles_whenArticlesAdded

Suggestion: getArticles_shouldReturnAllArticles_whenArticlesStored

Don’t just repeat the method signature

getArticles_shouldReturnListOfArticles_whenArticlesStored

This name is another case of “technically true, but not actually useful”. We can see from the getArticles return type that it should return a List<Article>.

What is more useful is to say what we expect the contents of that List to be: which is all the Articles that have been stored.

You can probably guess, this one.

Suggestion: getArticles_shouldReturnAllArticles_whenArticlesStored

Don’t mention irrelevant details

fetchArticles_shouldReturnAllArticles_whenMockedArticleFetcherReturnsArticles

How the outcome is achieved through mocking or other similar details shouldn’t be reflected in the test name. In this case, it is somewhat relevant that the ArticleFetcher returns Articles, but not that the ArticleFetcher is mocked, so long as the ArticleStore should behave the same way regardless.

Suggestion: fetchArticles_shouldReturnAllArticles_whenArticlesFetcherReturnsArticles

To be honest, that’s a bit of an indirect mouthful, so:

Alternative Suggestion: fetchArticles_shouldReturnAllArticles_whenArticlesReturnedByArticleFetcher

Using @DisplayName

JUnit 5 gives you the ability to define the test name, in a more readable way, separately from the test method using the @DisplayName annotation.

I’d like to be proven wrong, but this just seems like you would have two naming problems - one for the test method and the other for the display name. You’d also have to maintain them both too.

Perhaps it could be useful if you wanted to make your test case report look like you written the tests in Kotlin.

Kotlin

Speaking of which!

Kotlin gives you even more language freedom to define the test name in a more human-readable way by avoiding camel and snake case ugliness.

Still, you should decline the invitation to write an essay for a test name; try to keep your core naming structure intact.

`fetchArticles returns all Articles returned by the ArticleFetcher`

Conclusion

Just like perfection is the enemy of good, sometimes overly strict naming rules get in the way of writing good names. You’ll need to find a test name writing style that suits your team and the tests and be prepared to revisit it. You will discover that there are certain tests that are more easily described in one way than another. Perhaps you find one style of language is for whatever subjective reason, sits better with the team.

The situation you want to avoid is where the test name is an unhelpful description of the intention of the test. Help out your team and your future self and write considered and considerate test names.

Thanks for reading!

This post is Creative Commons Attribution 4.0 International (CC BY 4.0) licensed.