21

Usually when talking about coding standards we refer to the code of the program itself, but what about the unit tests? Are there certain coding standards guidelines that are unique to unit tests? What are they?

11

Off the top of my head, I can think of three differences in coding style for test code.

In naming test methods, I follow the pattern of shouldDoSomethingWhenSomeConditionHolds.

Inside the test, it is customary to follow the following spacing pattern:

@Test
shouldReturnAccountBalenceWhenGetBalenceIsCalled() {
    // Some lines 
    // of setup code
    // go here.

    // The action being tested happens after a blank line.

    // An assertion follows another blank line.
}

Some insist on only one assertion per test, but this is far from universal.

The DRY (Don't Repeat Yourself) is less of a consideration in test code than in production code. While some repeated code should be placed in a setUp method or a testUtils class, striving for zero repetition in test code will lead to tightly coupled and inflexible tests, which discourages refactoring.

  • Of course, there are a variety of patterns, which is why you should provide an answer too. – Eric Wilson Oct 31 '10 at 18:52
  • 10
    That's the Arrange , Act, Assert pattern. – StuperUser Jun 2 '11 at 13:22
  • DRY is still important. If you need to do same asserts in multiple tests, create common function and call it in all tests. – Michael Freidgeim Nov 30 '17 at 20:39
  • @MichaelFreidgeim Maybe we are just talking about degrees, but I have a significantly higher tolerance for repetition in test code. I have had several experiences of building test suites with very little repetition, and found that the tests became hard to modify and understand when requirements changed. Then I stopped worrying as much about DRY in tests, and my test suites have been easier to use. <shrug> – Eric Wilson Dec 1 '17 at 13:12
16

Roy Osherove recommends the following pattern for naming your tests:

NameOfMethodUnderTest_StateUnderTest_ExpectedBehavior() 

See http://weblogs.asp.net/rosherove/archive/2005/04/03/TestNamingStandards.aspx

  • I agree with Roy. It improves readability, eventhough ReSharper keeps telling me that I should remove them to NameOfMethodUnderTestStateUnderTestExpectedBehavior() ;) – Oscar Mederos Mar 8 '11 at 0:45
  • How to make this work when the method is overloaded, so there can be multiple methods with same name? – Narendra Pathai Jan 3 '14 at 8:09
5

The main thing is to remember that unit tests are essentially mini-specifications. This means that the emphasis must always be on readability.

Firstly, this means that names must clearly communicate what is under test and what is being asserted.

Secondly though, which is sometimes forgotten, is that as specifications they should be doing just that - specifying behaviour. That is, unit tests should not contain logic - or potentially they fall into the trap of repeating the program's functionality rather than testing it.

Sometimes the tests will involve objects which are complex to set up, you should strive to keep this set up logic separate from your tests using something like an object mother or a test data builder.

I'll just round off with a few book recommendations:

xUnit Test Patterns: Refactoring Test Code: Excellent book, some say it's a bit dry but I don't think so. Goes into a lot of detail about lots of different ways of organising tests and how to keep them maintainable. Relevant if you're using something like NUnit etc.

The Art of Unit Testing: With Examples in .Net: The best book on the nitty-gritty of writing and maintaining tests. Despite being really new I find the mocking sections a little dated already as AAA syntax is now pretty standard rather than just another way of doing it.

Growing Object-Oriented Software, Guided by Tests: This book is just amazing! By far the best unit testing book and the only advanced one which puts unit testing as a first class citizen in the design process. Was reading this when it was a public beta and been recommending since. Excellent real-worldish worked example used throughout the book. Would recommend reading Roy's book first though.

  • IMHO it's ok for unit tests to contain logic: It's perfectly reasonable to test a highly optimized, efficient version of an algorithm by using a naive algorithm that does the same thing to determine the correct behavior. For example, imagine testing a hash table by building a linear search-based associative array. – dsimcha Oct 31 '10 at 19:53
  • 2
    Yes, but that belongs outside the test in the test data builders (which should themselves be unit tested if the logic inside them isn't trivial). Exception to this would be 3rd party libraries which generally are "trusted" to be correct and could be used without tests. – FinnNk Oct 31 '10 at 20:07
3

Don't put logic in your unit tests. For example, let's say you're testing an add method, you could have something like this:

void MyTest_SaysHello()
{
   string name = "Bob";
   string expected = string.Format("Hello, {0}", name);
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello(name);
   Assert.AreEqual(expected, actual);
}

In this particular case, you're likely repeating the same logic as what's in the test, so you're essentially testing "1 + 1 == 1 + 1", rather than "1 + 1 == 2", which is the "real" test. So what you would really want your test code to look like is:

void MyTest_SaysHello()
{
   string expected = "Hello, Bob";
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello("Bob");
   Assert.AreEqual(expected, actual);
}
  • 2
    Small correction: I think you meant 'string expected = string.Format("Hello, Bob")' should be 'string expected = "Hello, Bob"'. – Mike Rosenblum Mar 8 '11 at 1:24
  • @MikeRosenblum you're obviously right, and someone tried to correct it, but two reviewers rejected this edit – Konrad Morawski Jan 15 '14 at 15:00
  • @Konrad: that's odd. This is a programming forum, right? – Mike Rosenblum Apr 2 '14 at 21:53
  • I've edited the answer once again as suggested by Mike Rosenblum. – bdsl Nov 5 '17 at 14:01
0

Long, descriptive method names. Remember, test methods are never called from code (they're called by the unit test runner that discovers and calls them via reflection), so it's OK to go crazy and have method names 50-80 characters long. Specific naming convention (camel-case, underscores, "should", "must", "when", "given", etc.) is not really important as long as the name answers three questions:

  • what is under test?
  • what are the conditions?
  • what is the expected result?

Test methods should be short.

Test methods should have a simple, linear structure. No if or loop constructs.

Test methods should follow the "arrange-act-assert" pattern.

Each test should test one thing. This usually means one assert per test. A test like { Do A; Assert B; Assert C; } should be refactored into two: { Do A; Assert B; } and { Do A; Assert C; }

Avoid random data or things like 'DateTime.Now'

Ensure that all test fixture members are returned to their original state at the end of the test (e.g. using a teardown)

Even if you remove duplication ruthlessly in your production code, code duplication in test fixtures is a much smaller concern.

-1

Somewhat similar to what Farmboy has already mentioned, My method name format

 <MethodName>Should<actionPerformed>When<Condition>

e.g

 GetBalanceShouldReturnAccountBalance() {

protected by gnat Nov 3 '17 at 21:28

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.