208

General

  • Follow the same standards for all tests.
  • Be clear about what each test state is.
  • Be specific about the expected behavior.

Examples

1) MethodName_StateUnderTest_ExpectedBehavior

Public void Sum_NegativeNumberAs1stParam_ExceptionThrown() 

Public void Sum_NegativeNumberAs2ndParam_ExceptionThrown () 

Public void Sum_simpleValues_Calculated ()

Source: Naming standards for Unit Tests

2) Separating Each Word By Underscore

Public void Sum_Negative_Number_As_1st_Param_Exception_Thrown() 

Public void Sum_Negative_Number_As_2nd_Param_Exception_Thrown () 

Public void Sum_Simple_Values_Calculated ()

Other

  • End method names with Test
  • Start method names with class name
Stacked
  • 6,892
  • 7
  • 57
  • 73
stung
  • 347
  • 5
  • 13
  • 27

7 Answers7

98

I am pretty much with you on this one man. The naming conventions you have used are:

  • Clear about what each test state is.
  • Specific about the expected behaviour.

What more do you need from a test name?

Contrary to Ray's answer I don't think the Test prefix is necessary. It's test code, we know that. If you need to do this to identify the code, then you have bigger problems, your test code should not be mixed up with your production code.

As for length and use of underscore, its test code, who the hell cares? Only you and your team will see it, so long as it is readable, and clear about what the test is doing, carry on! :)

That said, I am still quite new to testing and blogging my adventures with it :)

Community
  • 1
  • 1
Rob Cooper
  • 28,567
  • 26
  • 103
  • 142
  • 21
    Slight contradiction "so long as it is readable, and clear" and "who... cares". Well everyone cares when it isn't readable & clear, so that's why it matters. :-) – David Victor May 31 '12 at 11:41
  • 1
    One additional argument for prefix. When you are searching for a file in IDE, you can easily search test cases by starting off with `Test` and your class name. If the class name and the test class name is same, we are going to always have to pause and read the path of two files – THIS USER NEEDS HELP Jan 12 '18 at 00:26
  • 1
    @THISUSERNEEDSHELP I think your point can be easily overcome by having a good folder structure like **src/libs** & **src/tests** . I know the some test runner frameworks do require a prefix like _test_ for test code identification, so in those cases won't be avoided, but for the rest it can be a repetitive _no required_ prefix. – JeanCarlos Chavarria Jan 30 '19 at 17:45
  • @negrotico19 I am thinking of the case like in IntelliJ when you `Search Everywhere` (shift shift) or `Find a Class By Name` (CMD O). I get that it *will* be differentiated by either folder structure or module structure, but when we search for something, we already know what we want to search for. For example, if I am looking for a test, I want to limit my search to `test` and then search for the name, rather than searching the name and *then* filter out test manually by eyes. It's a small distinction, but it's much easier to "test [class name]" and have only one pop up and reduce mental load – THIS USER NEEDS HELP Jan 31 '19 at 18:49
38

This is also worth a read: Structuring Unit Tests

The structure has a test class per class being tested. That’s not so unusual. But what was unusual to me was that he had a nested class for each method being tested.

e.g.

using Xunit;

public class TitleizerFacts
{
    public class TheTitleizerMethod
    {
        [Fact]
        public void NullName_ReturnsDefaultTitle()
        {
            // Test code
        }

        [Fact]
        public void Name_AppendsTitle()
        {
            // Test code
        }
    }

    public class TheKnightifyMethod
    {
        [Fact]
        public void NullName_ReturnsDefaultTitle()
        {
            // Test code
        }

        [Fact]
        public void MaleNames_AppendsSir()
        {
            // Test code
        }

        [Fact]
        public void FemaleNames_AppendsDame()
        {
            // Test code
        }
    }
}

And here is why:

Well for one thing, it’s a nice way to keep tests organized. All the tests (or facts) for a method are grouped together. For example, if you use the CTRL+M, CTRL+O shortcut to collapse method bodies, you can easily scan your tests and read them like a spec for your code.

I also like this approach:

MethodName_StateUnderTest_ExpectedBehavior

So perhaps adjust to:

StateUnderTest_ExpectedBehavior

Because each test will already be in a nested class

Community
  • 1
  • 1
Robs
  • 8,219
  • 6
  • 41
  • 57
  • 2
    For those using Resharper's test runner in Visual Studio, they fixed bugs using nested test classes in 8.x. Since then, this became my preferred structure by far. – angularsen Mar 11 '15 at 12:44
  • 1
    Does it matter that the name becomes really long with the MethodName_StateUnderTest_ExpectedBehavior approach? Such as "InitializeApiConfiguration_MissingApiKey_IllegalArgumentException". Is this really a good test name? – portfoliobuilder Jun 21 '19 at 17:03
30

I tend to use the convention of MethodName_DoesWhat_WhenTheseConditions so for example:

Sum_ThrowsException_WhenNegativeNumberAs1stParam

However, what I do see a lot is to make the test name follow the unit testing structure of

  • Arrange
  • Act
  • Assert

Which also follows the BDD / Gherkin syntax of:

  • Given
  • When
  • Then

which would be to name the test in the manner of: UnderTheseTestConditions_WhenIDoThis_ThenIGetThis

so to your example:

WhenNegativeNumberAs1stParam_Sum_ThrowsAnException

However I do much prefer putting the method name being tested first, because then the tests can be arranged alphabetically, or appear alphabetically sorted in the member dropdown box in VisStudio, and all the tests for 1 method are grouped together.


In any case, I like separating the major sections of the test name with underscores, as opposed to every word, because I think it makes it easier to read and get the point of the test across.

In other words, I like: Sum_ThrowsException_WhenNegativeNumberAs1stParam better than Sum_Throws_Exception_When_Negative_Number_As_1st_Param.

CodingWithSpike
  • 42,906
  • 18
  • 101
  • 138
22

I do name my test methods like other methods using "PascalCasing" without any underscores or separators. I leave the postfix Test for the method out, cause it adds no value. That the method is a test method is indicated by the attribute TestMethod.

[TestMethod]
public void CanCountAllItems() {
  // Test the total count of items in collection.
}

Due to the fact that each Test class should only test one other class i leave the name of the class out of the method name. The name of the class that contains the test methods is named like the class under test with the postfix "Tests".

[TestClass]
public class SuperCollectionTests(){
    // Any test methods that test the class SuperCollection
}

For methods that test for exceptions or actions that are not possible, i prefix the test method with the word Cannot.

[TestMethod]
[ExpectedException(typeOf(ArgumentException))]
public void CannotAddSameObjectAgain() {
  // Cannot add the same object again to the collection.
}

My naming convension are base on the article "TDD Tips: Test Naming Conventions & Guidelines" of Bryan Cook. I found this article very helpful.

jeremcc
  • 8,633
  • 11
  • 45
  • 55
Jehof
  • 34,674
  • 10
  • 123
  • 155
  • 1
    +1 for link to my post -- though it's unnecessary to use a "Test" prefix in your Tests. Be sure that your tests specify the expected behavior. For example, CanRetrieveProperCountWhenAddingMultipleItems() – bryanbcook Sep 02 '09 at 14:55
  • 2
    I don't like it because it does Not include the expected behaviour – Johannes Rudolph Sep 03 '09 at 09:25
5

The first set of names is more readable to me, since the CamelCasing separates words and the underbars separate parts of the naming scheme.

I also tend to include "Test" somewhere, either in the function name or the enclosing namespace or class.

Frank Szczerba
  • 5,000
  • 3
  • 31
  • 31
  • 2
    @Frank methodName = camelCase MethodName = PascalCase – Metro Smurf Jun 13 '09 at 21:41
  • @metro-smurf: interesting distinction, I've never heard the term PascalCase used, and I've been doing this for a long time. I only see the term PascalCase come up in Microsoft developer circles, is that what you do? – Frank Szczerba Jun 19 '09 at 19:02
  • History around Pascal Casing and Camel Casing (from: Brad Abrams - http://blogs.msdn.com/brada/archive/2004/02/03/67024.aspx )... "In the initial design of the Framework we had hundreds of hours of debate about naming style. To facilitate these debates we coined a number of terms. With Anders Heilsberg (the original designer of Turbo Pascal) a key member of the design team, it is no wonder that we chose the term Pascal Casing for the casing style popularized by the Pascal programming language." – Riegardt Steyn Feb 05 '13 at 13:13
-3

As long as you follow a single practice, it doesn't really matter. Generally, I write a single unit test for a method that covers all the variations for a method (I have simple methods;) and then write more complex sets of tests for methods that require it. My naming structure is thus usually test (a holdover from JUnit 3).

Munger
  • 43
  • 1
-7

I use a 'T' prefix for test namespaces, classes and methods.

I try to be neat and create folders that replicate the namespaces, then create a tests folder or separate project for the tests and replicate the production structure for the basic tests:

AProj
   Objects
      AnObj
         AProp
   Misc
      Functions
         AFunc
   Tests
      TObjects
         TAnObj
            TAnObjsAreEqualUnderCondition
      TMisc
         TFunctions
            TFuncBehavesUnderCondition

I can easily see that something is a test, I know exactly what original code it pertains to, (if you can't work that out, then the test is too convoluted anyway).

It looks just like the interfaces naming convention, (I mean, you don't get confused with things starting with 'I', nor will you with 'T').

It's easy to just compile with or without the tests.

It's good in theory anyway, and works pretty well for small projects.

user566399
  • 11
  • 2
  • 3
    Interesting approach. Some people may argue that the T prefix conflicts with convention you use in generics (e.g. func(T1, T2, TResult)), but I personally don't care as long as there's a consensus within the team. The names are short which makes things more readable too. – stung Jan 10 '11 at 22:00
  • Too Hungarian (notation) for me. Also, ad stung stated, prefix T is used for generic type parameters. – Danny Varod Jun 21 '11 at 08:14
  • I agree, Hungarian notation has been depricated and because the conflict with standard generic type parameters, I don't see an exception applying in this case (like there is for interfaces). – SonOfPirate Dec 13 '11 at 13:19