DEV Community

Lars Richter
Lars Richter

Posted on

How do you name your tests?

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 naming schemes for unit tests. A few of them are:

[MethodUnderTest]_[TestedState]_[ExpectedBehavior]

That's a classical naming scheme.

ReadFrom_FileDoesNotExist_ThrowsException

[MethodUnderTest]_[ExpectedBehavior]_[TestedState]

This is pretty similar to the first scheme. Personally, I like this one a little better than the first one. This one reads a little more naturally. For example:

ReadFromFile_ThrowsException_FileDoesNotExist

It reads almost like "WriteToFile throws an exception if file does not exist".

Should_[ExpectedBehavior]_When_[TestedState]

Should_ThrowException_When_FileDoesNotExist

This also reads almost like a "normal" sentence.

When_[TestedState]_Expect_[ExpectedBehavior]

When_FileDoesNotExist_Expect_WriteToFailToFail

Given_[Preconditions]_When_[TestedState]_Then_[ExpectedBehavior]

Given_ReportIsWrittenToFile_When_FileDoesNotExist_Then_ExceptionIsThrown

JustDescribeWhatIsGoingOnAndWhatShouldHappen

This is something I fall back to from time to time. In these cases, my test read something like this:

OrderProcessorThrowsAnExceptionInCaseOfMissingCustomer

These are just a few examples. Feel free to add some more naming schemes in the comments.

Whats your favorite naming scheme? Are there naming schemes you do not like?

Discussion (10)

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 Author

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 Author

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

Collapse
n_develop profile image
Lars Richter Author

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 Author

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 Author

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.