What’s in a Name?
It’s important to choose a useful name for a test. If tests are documentation, test names are the chapter headings.
Test Names Should Not Include Should
There’s nothing wrong with the word “should.” It’s just not necessary. It’s one more word to read when trying to understand a test. “It should divide by four” and “It divides by four” express the same idea in a test name.
it "foo should return the correct answer when passing in a date" do end
There are several issues with the above. First of all, it contains should. Second, it runs roughshod over ‘it.’ If I read the line out loud, “it foo…” does not make sense. Also, that’s a lot of words. As a developer, I want to be able to skim the tests so that I can find the test case I’m looking for.
describe "foo" do describe "when passing in a date" do it "returns the correct value" do end end end
Isn’t that better? In addition to being more readable, it makes it painfully obvious that we’re missing another test case. Let’s add it.
describe "foo" do describe "when passing in a date" do it "returns the correct value" do end end describe "no date passed in" do it "returns the correct value" do end end end
Now we have another issue: two test cases called “returns the correct value.” Come to think of it, that’s also pretty generic. Probably most test cases could be called “it returns the correct value,” “it has the intended side-effects,” or “it has the intended side effects and returns the correct value.” The question is, how would you describe the value and/or side-effect we’re looking for? Not the actual value, but its significance or meaning.
describe "foo" do describe "when passing in a date" do it "returns the count of bars before the date" do date = Date.today assert_equal 2, foo(date) end end describe "no date passed in" do it "returns the count of all bars" do assert_equal 4, foo end end end
Cool. Now in this one-assertion test it doesn’t matter as much, but say we returned the bars themselves instead of the count and needed to make several assertions. Like test names, variable names in assertions improve readability.
expected_count = 2 expected_dates = ['2011-04-15', '2017-01-01'] result = foo assert_equal expected_count, result.count assert_equal expected_dates, result.map(&:date)
A Bit of Context
describe "foo" do context "when passing in a date" do it "returns the count of bars before the date" do end end end
describe when specifying the subject of the test – the class or method. Use
context when talking about the circumstances under which we’re testing.
Let’s write some tests for our tests:
- it “begins with a verb, not a subject” (‘it’ is the subject)
- it “reads like a sentence” (‘it’ is the first word of the sentence)
- it “does not contain when or if” (those belong in describe blocks)
- it “is short” (and skimmable)
- it “doesn’t use should as the verb”
- it “is specific about the expected result” (what is the significance of the correct or expected result?)