DEV Community

How do you name your tests?

Lars Richter on June 16, 2019

As you might know, I'm a big fan of unit testing and TDD. But I often go back and forth on the naming of my unit tests. There are many popular nami...
Collapse
 
easyaspython profile image
Dane Hillard

In Python land I typically name my methods test_[method under test]_[expected behavior]?_when_[preconditions], so my tests look like:

def test_extract_name_when_present(...):
    ...

def test_extract_name_fails_when_missing(...):
    ...

With my recent adoption of pytest for a lot of stuff, though, I also parameterize tests where I can which ends up making the test method names more generic.

Collapse
 
n_develop profile image
Lars Richter

I like parameterized tests as well. It's a nice way to cover multiple cases, that share the same assert statements.

I'm not great at Python. Is the "test_" at the beginning of the method required for the testrunner to identify the tests, or is it "just" convention?

Collapse
 
easyaspython profile image
Dane Hillard

Yep, that's often the pattern that a test runner looks for! I think most can be customized to find other patterns too, and I recently saw a pytest plugin that makes it easy not to have to type "test" so many times in code you already know is tests.

Collapse
 
dorshinar profile image
Dor Shinar

Lately I've been writing mostly JS, and I am quite fond of the way Jest/mocha tests are written:

describe("SomeClass", () => {
  it("does something when something happens", () => {
    // Test code
  }
}

This way you actually write coherent sentences to describe your tests, not needing some elaborate convention.

Collapse
 
n_develop profile image
Lars Richter

That reads pretty nice, indeed. I should definitely check if there is something comparable for C#.

Collapse
 
n_develop profile image
Lars Richter

I'm learning Go right now and found, that it has a similar concept.

func TestSum(t *testing.T) {
    t.Run("collection of 5 elements", func(t *testing.T) {
        numbers := []int{1, 2, 3, 4, 5}

        got := Sum(numbers)
        want := 15

        if want != got {
            t.Errorf("got '%d' want '%d', %v", got, want, numbers)
        }
    })
    t.Run("collection of any size", func(t *testing.T) {
        numbers := []int{1, 2, 3, 4, 5, 6, 7, 8}

        got := Sum(numbers)
        want := 36

        if want != got {
            t.Errorf("got '%d' want '%d', %v", got, want, numbers)
        }
    })
}

I like it.

Collapse
 
renegadecoder94 profile image
Jeremy Grifski • Edited

Really great list! I didn’t realize there were actual naming patterns. I’m usually pretty lazy and write something like test[method name][input/state].

If I were more disciplined, I might follow something that mirrors what I was taught. In particular, I was taught to follow a first, middle, last and 0, 1, many test pattern, so that might be a good way to name tests as well.

Collapse
 
n_develop profile image
Lars Richter

Interesting. I learned writing Tests with the "0,1,some,lots,oops" pattern. It differentiates between "some" data and "lots of" data. And "oops" means handling error cases.

Collapse
 
haidv profile image
HaiDV

I choose Should_[ExpectedBehavior]When[TestedState] way to describe my test because when I come back and read my test, I feel this way make the test more readability, naturenality

Collapse
 
n_develop profile image
Lars Richter

Readability is key. And yes, this pattern is readable.
That's why I do like the Given_[Preconditions]_When_[TestedState]_Then_[ExpectedBehavior] pattern. It also reads like a normal sentence.