One weird trick to name your tests

You’re crushing code and taking names. You got a gajillion dollars in VC funding and the world domination is just a lisp macro away.

But you’re also a sensible professional engineer with a heart of gold and you care about the quality of your work. Tests and readability matter to you and you’re not gonna compromise on those for arbitrary business deadlines. You don’t just write code, YOU MAKE ART!

But naming things is hard. Especially naming tests so that they make sense to someone who hasn’t pair-programmed with you since kindergarten. So let’s see how we can christen our tests better, shall we?

One weird trick for naming tests

Take a look at this test:

public void loginFails() {
  authenticator.login(“user@email.com”, “wrong password”);
  assertFalse(authenticator.isUserLoggedIn());
}

To understand what is being tested, you’re gonna have to read the test and figure that the login is supposed to fail when a wrong password is provided.

In other words, the test is missing a context. You can see that login is supposed to fail but you don’t know under what conditions.

Consider the same test with a different name:

public void wrongPasswordTest() {
  authenticator.login(“user@email.com”, “wrong password”);
  assertFalse(authenticator.isUserLoggedIn());
}

Once again, you’ll have to read the test code to see what’s going on. In this case, You know you’re testing the wrong password scenario but you don’t know what is supposed to happen upon encountering it.

This test is missing an expectation.

So let’s take this caterpillar and turn it into a butterfly, shall we?

Here’s the one weird trick that will vault you into the test naming hall of fame:

Test names should have a clear scenario and a clear expectation

That’s it. There’s no more magic to it than that. The test would read much better if it looked like this:

public void loginShouldFailOnWrongPassword() {
  authenticator.login(“user@email.com”, “wrong password”);
  assertFalse(authenticator.isUserLoggedIn());
}

Naming styles

Now that you know that your test names should contain both a scenario and an expectation, there are many different styles you could choose from. Any of them will do just fine and it’s mostly a matter of taste. Your taste of course, is better than everyone else’s.

  • method_scenario_expectation : Using this style, The test name would be login_onWrongPassword_shouldFail(). The disadvantage here is if that you change the method name, your IDE refactoring tool will probably not change the test name as well forcing you to do it manually.
  • expectationScenario : Here, The test name would be shouldFailToLoginOnWrongPassword(). Terse and simple, this style is quite popular.
  • scenario1_scenario2_expectation : A slight variation on the previous version allows more readable naming on multiple related scenario conditions. For example, if we have a behaviour that should happen on the third login attempt with a wrong password, we could call our test: onLoginWithWrongPassword_onThirdAttempt_shouldShowErrorDialog().
  • given_when_then : This one comes from BDD and has the advantage of adding more context information to the scenario. This looks something like : givenUserIsLoggedOut_whenUserTriesLoginWithWrongPassword_shouldFailToLogin().

You might see some more test naming conventions in the wild but they’ll mostly be some variation of the above styles. Whichever one you choose, make sure you stick with it throughout your project. One of the worst things you could do is have haphazard naming styles scattered throughout the same project. That’s for noobs. Not elite devs like us amirite?

Moral of the story

Every test name should contain a clear scenario and an expectation. This makes it easier to grok and easier to refactor.

Keep hacking.


If you liked this, click the 👏 below. I notice each one and I’m grateful for every one of them.

For more musings about programming, follow me so you’ll get notified when I write new posts.