How do I name my test methods?

Tips for effective naming your XCTestCase methods

Hello there! It's great to be back here, ready to dive into unit testing again. Today, I want to share some valuable techniques that I personally use to give effective names to my unit test methods. Naming things can be a challenge for many developers, including myself. Whether it's classes, variables, functions, or methods, finding the right name often requires some extra thought. And when it comes to unit tests, this challenge becomes even more apparent.

The Problem

I've found myself spending more time brainstorming a good name for my test than actually writing the test itself. It's essential to strike a balance between expressing the test's intent and keeping the name concise and easy to read. After all, when someone reviews your code or looks at the CI log, they want to understand the test's purpose quickly. So, in this post, I'll share some techniques that may come in handy when you face this naming dilemma.

But before we get into the techniques, let's talk about some conventions and patterns that can make your test names more consistent and comprehensible, especially when working in larger teams.

Conventions and Patterns

To start, it's helpful to establish a consistent pattern or template for naming your test methods. Having a standardized format benefits everyone involved. It enables developers to understand each other's code more easily and write new code faster. Here are a couple of aspects to consider

Line length

Nobody enjoys scrolling horizontally through code, especially during code reviews or when reading a CI log. So, I strongly recommend setting a maximum line length for your method names. Long test names can be a sign of underlying issues, such as complex setups or obscure conditions. It's an opportunity to reassess the design of the subject being tested.

You can choose a suitable line length for your project, but I suggest aiming for a range between 90 and 130 characters. This ensures that your test names fit comfortably on a GitHub page without requiring line breaks or horizontal scrolling. To make it easier to adhere to this restriction, you can enable the page guide in your editor. In Xcode, go to Xcode > Preferences > Text Editing and check the "Page guide column" option.

Enable page guide checkbox

Once enabled, the page guide will be visible in your editor, helping you stay within the desired line length.

Page guide being shown on code editor

Formatting

Deciding on a consistent format for your test names is crucial. You can choose from lowercase, uppercase, camel-case, or snake-case—whatever works best for your project. Personally, I start my test names with the test_ prefix.

It's also helpful to adopt a specific casing pattern for your method names. I prefer using lower-camel case, where each word starts with a lowercase letter except for the first word. Here's an example to illustrate the point:

✅ Do:

func test_deselectsItemUponSecondTap()

🛑 Don’t:

// Doesn't have the defined underscore
func testDeselectItemUponSecondTap()
// Snake case
func test_deselect_item_upon_second_tap()
// Mixed cases
func test_deselectItem_uponSecondTap()

You might wonder why I recommend adding an underscore (_) after the test prefix. This practice serves a specific purpose—to separate the test keyword from the test's intent, which will be explained in more detail in the next section.

By introducing this visual separation, we create a clearer distinction between the standardized test prefix and the descriptive part of the test name. It enhances readability and makes it easier for developers to quickly identify that a method is a test method.

Once you've established these conventions and patterns, you're ready to move on to the next step.

Expressive Test Summaries

A well-crafted test name should provide a concise summary of what is being tested. This is the most challenging part, but here's a useful approach to consider. Imagine you're writing a commit message, and try to complete the following sentence:

  • "This test ensures that the SUT (System Under Test) ...

Let me give you a few examples:

... deselects an item upon a second tap."

... shows content on a successful response."

... returns the preferred payment method."

... completes with a not-found error on invalid URLs."

Keep it simple. Just complete the sentence using the Simple Present tense. By doing this, you focus on the behavior or functionality of the SUT without including details about spies, collaborators, class names, or implementation specifics. This approach makes your tests more flexible when it comes to refactoring.

To comply with the line length restrictions, you may need to omit some article words. Remember, the goal is to create test summaries that are clear and concise.

✅ Do:

func test_showsContentOnSuccessfulResponse()
func test_returnsPreferredPaymentMethod()
func test_completesWithNotFoundErrorOnInvalidURLs()

🛑 Don’t:

// Unecessary verbosity
func test_givenASuccessfulResponseWhenTheScreenAppearShouldShowSomeContent()
// Past tense
func test_returnedPreferedPayment()
// Too coupled with implementation details
func test_completesWith404ErrorFromTheNetworkingForURLRequestsWithInvalidURLs()

Conclusion

These are some of the standards and techniques that have proven effective in my unit tests. They have greatly helped both my team and me, and I hope they can do the same for you. Of course, keep in mind that this post reflects my personal opinions and experiences, so feel free to adapt these techniques to fit your specific context. Thank you for taking the time to read this post! Until next time!

Did you find this article valuable?

Support Will Policiano by becoming a sponsor. Any amount is appreciated!