Readable test code matters.

Readable code matters

Developers spend much more of their time reading than writing.

Give your tests good names.

Having clear intention in your tests is important. There are lots of good patterns to follow when naming tests. Upon reading a range of opinions, I found 3 common elements in any naming pattern for tests.

  • The system under test. This is the method, module, class, or route under test.
  • The state under test. The context that the test occurs. For example, if you need to arrange specific data such as “user already signed in”.
  • The expected behavior of the test. The desired return value or expected state of your system.
test "User.signIn _ user is already signed in _ redirect to home"
  • The system under test: User.signIn
  • The state under test: user is already signed in
  • The expected behavior: redirect to home

Realworld example

The important piece to remember is not following a particular standard. Instead, it’s to make sure that your test name captures the right information.

test "User.signIn _ user is already signed in _ redirect to home"
  • The system under test: GET /authors/log_in
  • Expected behavior: redirects
  • State under test: already logged in

The three A’s of testing (arrange, act, assert)

In case you are not familiar with the three A’s of testing, they are:

  • Arrange: set up the data necessary to perform the test.
  • Act: trigger the action to test. Usually, this is a specific method or action that you’re testing.
  • Assert: now that you’ve triggered that action, assert that your system behaved as you expect.
  • Arrange == state under test
  • Act == system under test
  • Assert == expected behavior

Common Naming Conventions

There are many common naming conventions for tests. Most if not all of them try to capture the information above. Rather than recommending a specific convention, I’d like to help you understand why they exist and how you can pick your own.

  • Given _ state under test _ when _ system under test _ then _ expected behavior
  • Should _ expected behavior _ when _ state under test
  • The system under test _ state under test_ expected behavior

Tests still get out of date.

Now you know how to give your tests readable names. But as your application grows and changes, it’s still inevitable that your tests will become out of date.

Names Change

Tests can become out of date is due to renaming. Here’s some pseudo-code to illustrate renaming a method from login to signin and a class from UserClass to AuthClass.

test "UserClass.login _ renders log in page"
AuthClass.signin()
assert current_route === "/login"

Behavior changes

Product demands constantly change to fit user demands. This is not a bug; it’s a feature.

test "User.signIn _ user is already signed in _ redirect to home"
UserClass.signin()
assert current_route === "/"
# "redirect to home" should be "log in as different account"
test "User.signIn _ user is already signed in _ redirect to home"
UserClass.signin()
assert current_route === "/log_in_as_different_account"

How to make your tests more maintainable

Now that you know how tests go out of date, what can you do to make them easier to maintain?

Consider excluding the expected behavior in the test name

You may choose to use a pattern that doesn’t include the expected behavior in the test name. Instead, the expected behavior is made clear in the assertion at the end of the test.

test "UserClass.signin _ user already signed in"
UserClass.signin()
expectRedirectedToHome()
test "UserClass.signin _ user already signed in"
UserClass.signin()
expectRedirectedToChooseAnotherAccount()

Consider putting the system under test in the describe block

For tests sharing the same system under test, consider grouping them, so you only have to refactor the name in one place.

Conclusion

Making your code readable is as important as making it work. Therefore, your test code should maintain a standard of readability, just like any other code in your system.

  • The system under test
  • The state under test
  • The expected behavior of the test.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Brooklin Myers

Brooklin Myers

Software Engineer. I create educational content focused on technology for mobile and web applications.