Search The Blog
My Books

New:

My Songs

 

The Art of Unit Testing

Buy PDF or Print book at Manning

Buy on Amazon

Latest Posts
from 5whys.com
Twitter: @RoyOsherove
About this site

TDD in .NET Online Course

TDD and BDD in Ruby Online Course

 

Subscribe!

This site aims to connect all the dots of my online activities - from tools, books blogs and twitter accounts, to upcoming conferences, engagements and user group talks.

« A Unit test should test only one thing | Main | [Interview]Kieran Mockford, MSBuild Program Manager - on MSBuild, TDD, the Microsoft build process and much more »
Sunday
Apr032005

Naming standards for unit tests

The basic naming of a test comprises of three main parts:

 [UnitOfWork_StateUnderTest_ExpectedBehavior]

A unit of work is a use case in the system that startes with a public method and ends up with one of three types of results: a return value/exception, a state change to the system which changes its behavior, or a call to a third party (when we use mocks). so a unit of work can be a small as a method, or as large as a class, or even multiple classes. as long is it all runs in memory, and is fully under our control.

Examples:

Public void Sum_NegativeNumberAs1stParam_ExceptionThrown()

Public void Sum_NegativeNumberAs2ndParam_ExceptionThrown ()

Public void Sum_simpleValues_Calculated ()

Reasons:

Test name should express a specific requirement

Your unit test name should express a specific requirement. This requirement should be somehow derived from either a business requirement or a technical requirement. In any case, that requirement has been broken down into small enough pieces, each of which represents a test case. If your test is not representing a requirement, why are you writing it? Why is that code even there?

Also, developers who are on a role are happy to give meaningless or numbered names to their test just so they can continue on with what they are doing. This leads down a narrow slope where quickly no one has the time or energy to fix the names of the tests. Also, most developers don t bother too much with writing good assert messages in their tests. A good assert message (which shows up if the test fails) is jey to understanding what went wrong. Assuming writing good assert messages is one of the key places where most unit test developers fall short, the only thing left to save us then is the name of the test. If both the name of the test and the error messages in it are not expressive enough, the poor maintenance developer (often the same one who developed the tests) is left to wonder what was this joker thinking? looking at a year old code base with unit tests.

Test name should include the expected input or state and the expected result for that input or state

To express the specific requirement clearly you should think about two things you need to express: the input values/current state during which the test takes place, and the expected result from that state.

Example:

Given this method :

Public int Sum(params int[] values)

You have a requirement that numbers larger than 1000 that are passed in should not be considered for calculation (that is a number bigger than 1000 is equal to zero).

What about this name: Sum_NumberBiggerThan1000

That is only half way there. As a reader of the test I can only assume that some input in your test is bigger than 1000, but I do not understand what the requirement being tested is.

How about this name: Sum_NumberIsIgnored

Still not good enough. While it does tell me the expected result, it does not tell me under which circumstances it needs to be ignored. I would have to go into the test code and read through it to find out what the expected input is.

How about this name: Sum_NumberIgnoredIfBiggerThan1000

That s much better. I can tell just by looking at the test name what It means if the test fails. I don t need to look at the code, and I can tell exactly what requirement this test tries to solve.

Test name should be presented as a statement or fact of life that expresses workflows and outputs

Unit tests are just as much about documentation as they are about testing functionality. You should always assume that someone else is going to read your tests in a year, and that they should not have a hard time understanding your intent.

Test names which are written as short declarative statements are much more expressive that names which are machine readable that is they only make sense if you have an understanding of a hidden code language to dissect their meaning.

People might first complain that the name of the test method appears way too long for them, but in the end it s more about readability. Longer test names do not imply longer or less optimized code, and even if they did, we are not looking to optimize test code performance. If anything, test code should always be optimized for readability.

Here s an example of a bad an d good test name

Public void SumNegativeNumber2()

And here s a better way to express your intent

Public void Sum_ExceptionThrownOnNegativeNumberAs2ndParam ()

Test Name should only begin with Test if it is required by the testing framework or if it eases development and maintenance of the unit tests in some way.

Since most tests today reside in a specific class or module that is logically defined as a test container (fixture), there are only a handful of reasons why you would want to prefix you test methods with the word Test :

- Your unit testing framework requires this

- You have coding standards in place and they include this

- You want to make it easier to navigate to the methods using Intellisense or some other search mechanism.

Test name should include name of tested method or class

You usually have at least a number of tests for each method you are testing, and you are usually testing a number of methods in one test fixture (since you usually have a test fixture per class tested). This leads to the requirement that your test should also reflect the name of the method begin tested, not only the requirements from it.

For example:

   [MethodName_StateUnderTest_ExpectedBehavior]

Public void Sum_NegativeNumberAs1stParam_ExceptionThrown()

Public void Sum_NegativeNumberAs2ndParam_ExceptionThrown ()

Public void Sum_simpleValues_Calculated ()

Public void Parse_OnEmptyString_ExceptionThrown()

Public void Parse_SingleToken_ReturnsEqualToeknValue ()

Naming Variables in a test:

Variable names should express the expected input and state

It s easy to name variables going into a method with generic names, but with unit tests you have to be twice as careful to name them as what they represent, i.e. BAD_DATA or EMPTY_ARRAY or NON_INITIALIZED_PERSON

You do not need to name them with a CONST casing , but the name does have to represent the intent of the test author.

A good way to check if your names are good enough is to look at the ASSERT at the end of the test method. If the ASSERT line is expressing what your requirement is, or comes close, you re probably there.

For example:

Assert.AreEqual(-1, val)

Vs.

Assert.AreEqual(BAD_INITIALIZATION_CODE, ReturnCode, Method shold have returned a bad initialization code )

PrintView Printer Friendly Version

Reader Comments (8)

Thanks for good article.

December 6, 2010 | Unregistered CommenterNagiah

The Art of Unit Testing is an excellent book for beginners and experts alike!

December 15, 2010 | Unregistered CommenterSeth Arakelian

I observed that MethodName_StateUnderTest_ExpectedBehavior is similar with given/when/then in other order (more useful for long testing methods list): when_given_then.

When - MethodName, or many methods names if needed, or action without associated with specific method.
Given - state at test moment.
Then - excepted result.

December 23, 2010 | Unregistered CommenterMikhail

We get an error for using the convention [MethodName_StateUnderTest_ExpectedBehavior]
by FxCop becuase '_' is not allowed for a member. How to solve this?

Should we use separate CodeAnalysisDictionary for Test Projects?

April 11, 2011 | Unregistered CommenterSanjay

Thanks.
excellent article.

May 29, 2011 | Unregistered CommenterMohamed

Sanjay, if you cannot use _, is there another non-alphanumeric character you could use? Or perhaps use 0 or x? The important thing is to give a descriptive name, so plain CamelCase will do it. For example:

MethodName0StateUnderTest0ExpectedBehavior
MethodNamexStateUnderTestxExpectedBehavior
MethodNameStateUnderTestExpectedBehavior

July 6, 2011 | Unregistered CommenterHugo

I have extended these recommendations for integration test methods using BizUnit. See http://geekswithblogs.net/charliemott/archive/2010/07/05/naming-standards-for-bizunit-integration-tests.aspx.

July 15, 2011 | Unregistered Commentercharliemott

I have yet to see a convention better than this, that makes more sense. It's great and an easy on every dev on your team can go by and tests just always make sense when you abide by this convention...so it's a no brainer to use it to me at least.

October 24, 2013 | Unregistered CommenterDave Schinkel

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>
Web Analytics