What are some popular naming conventions for Unit Tests? [closed]
Asked Answered
C

7

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
Cantu answered 18/9, 2008 at 20:0 Comment(1)
See Behavior Driven Development.Ilona
F
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 :)

Fioritura answered 18/9, 2008 at 20:32 Comment(4)
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. :-)Cervantes
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 filesProsy
@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.Solvency
@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 loadProsy
K
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

Kellene answered 18/9, 2008 at 20:0 Comment(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.Aleman
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?Pembroke
I
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.

Ionization answered 18/9, 2008 at 20:0 Comment(0)
I
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.

Intension answered 18/9, 2008 at 20:0 Comment(2)
+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()Rigby
I don't like it because it does Not include the expected behaviourOdorous
F
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.

Fogbow answered 18/9, 2008 at 20:4 Comment(3)
@Frank methodName = camelCase MethodName = PascalCaseSunbonnet
@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?Fogbow
History around Pascal Casing and Camel Casing (from: Brad Abrams - 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."Lathi
A
-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).

Accusatory answered 18/9, 2008 at 20:4 Comment(0)
M
-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.

Mucky answered 18/9, 2008 at 20:0 Comment(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.Cantu
Too Hungarian (notation) for me. Also, ad stung stated, prefix T is used for generic type parameters.Quinones
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).Rydder

© 2022 - 2024 — McMap. All rights reserved.