DEV Community

Gregory Paciga
Gregory Paciga

Posted on • Originally published at gerg.dev on

Don’t “check” or “verify” in your tests

Clearly communicating intent is an underrated skill in writing tests. In automated tests especially it is tempting to think that since the code defines what gets checked, the human-readable parts of the test — the description or the method names — aren’t as important to get right.

I often see people define custom assertion functions to avoid duplicate code (a good thing!) but then end up giving them names like this:

verifySystemState() { ... }
checkReturnCode() { ... }
Enter fullscreen mode Exit fullscreen mode

The problem with this is that instead of describing what the system does, they’re describing what the test does. The test is going to verify the system state or check the return code. In most code this makes sense: functions should say what they do, and usually how they do it shouldn’t matter to the caller. With functions used in tests, that’s only partially true. I still might not need to know how the thing is verified or checked—I can always go to the function definition for that—but as a reader care a lot more about why I’m calling that function than what the function does. The name should reflect that.

I see the same mistake made on test names and descriptions themselves. Constructions like this:

it("checks the response code", () => { ... });
Enter fullscreen mode Exit fullscreen mode

is (incorrectly!) describing what the test does: The test checks the response code. Almost every JavaScript test framework I’ve used allows using either test or it as the function name defining a test. Take advantage of what it here means: it’s not an abbreviation or shorthand for something technical, it’s meant to be read as the first word in that specification describing the system. Constructions like:

describe("Foobar", () => {
    it("should be a woozle", () => { ... });
    it("should return an array", () => { ... });
    it("throws an error when called with a boolean", () => { ... });
});
Enter fullscreen mode Exit fullscreen mode

are a series of sentences describing a Foobar, not describing the test:

  • It should be a woozle.
  • It should return an array.
  • It throws an error when called with a boolean.

Less charitably, this can also be a side effect of the writer not really understanding the system being tested. Take test names like these:

it("checks the return code", () => { ... });
it("handles arrays", () => { ... });
it("returns", () => { ... });
Enter fullscreen mode Exit fullscreen mode

Writing “it checks the return code” might be an answer to thinking “I should probably check what the return code is” rather than thinking “This should return a 200 OK so let’s write a test for that.” All of those examples suggest the writer had an idea of what to do next but little idea why or what to expect when they did it. Even if they did, a reader trying to understand these tests in 6 months surely won’t.

Instead of being written as commands telling the test automation what to do next, these test names and methods should answer a question or be a statement of fact.

  • Question: “What should the return code be?”
  • Answer: “It should be a 200 OK.”

It’s useful to module them after normal assertions or expectations:

expect(result).toEqual(value);
expect(getSystemState()).toEqual(expectedState);
assert(response.statusCode).toEqual(HTTP_OK);
Enter fullscreen mode Exit fullscreen mode

Wrapping the details of how we get the necessary information in helper functions, we’d use function names like:

expectSystemState(expectedState);
expectStatusIs200();
Enter fullscreen mode Exit fullscreen mode

(I’m still being a bit messy here using very generic sounding names; I get equally annoyed at variable names like “result” and “value” in real test code.) The point is the structure: “X is Y“, not “Do Z“.

While you can still create better names using “verify”:

verifyResponseCodeIs200();
Enter fullscreen mode Exit fullscreen mode

it’s too easy to drop the “is Y” part when “Verify X” is still a complete sentence. Slightly better, while “Check X” is a complete sentence, “Check that X” is not.

A strict rule for it would be silly, but if helps, put “check” and “verify” on your list of weasel words to avoid in test automation. While not themselves as bad gems like “correct” and “valid”, they’re enablers of ambiguity.

Top comments (0)