Skip to content

Best Practices

Robert Coltheart edited this page May 8, 2019 · 11 revisions

Contents

  1. General advice
    1. Consider using Subject to enhance test output
    2. Prefer nested context classes over inherited classes
  2. Delegate usage
    1. It should be a single line statement
    2. Stick to Arrange-Act-Assert conventions
  3. Naming conventions
    1. Consider naming contexts and specs from a users' point-of-view
    2. Test classes should be Snake_cased
    3. Fields in a context should be snake_cased
  4. Formatting
    1. Do not use visibility modifiers
    2. Put lambda expressions on new line
    3. Do not use braces for single-line lambdas
    4. Fields should appear first in a class

General advice

Consider using Subject to enhance test output

The Subject attribute will be used in formatting the test run output so it's advisable to use it to customize the display. Typically it should identify the name or type of the class under test.

It will also guide ReSharper (if you use it) to not mark any It delegates as 'unused' fields.

Right:

[Subject(typeof(Car))]

Prefer nested context classes over inherited classes

Using nested context classes is preferred to using base classes for the following reasons:

  • It improves readability as all test code is in the one place
  • Establish delegates can be used to 'share' setup of the class under test
  • Tests can be grouped sensibly

However, be warned that too much nesting of classes can also be confusing, so try to strike a balance.

Right:

class When_using_a_car
{
    Establish context = ... ;

    class When_the_car_moves_forward
    {
        Establish context = ... ;
    }
}

Delegate usage

It should be a single line statement

Right:

It should_turn_off_engine = () =>
    stopped.ShouldBeTrue();

Wrong:

It should_turn_off_engine = () =>
{
    var stopped = car.Stop();

    stopped.ShouldBeTrue();
}

Stick to Arrange-Act-Assert conventions

Establish is for arrange, Because is for acting, and It should be used for asserting.

Naming conventions

Consider naming contexts and specs from a users' point-of-view

Right:

class When_using_a_car
{
    static bool is_stopped;

    Because of = () =>
        is_stopped = car.StopCar();

    It should_turn_off_the_engine = () =>
        is_stopped.ShouldBeTrue();
}

Wrong:

class Car_tests
{
    static bool value;

    Because of = () =>
        value = car.StopCar();
    
    // What should be true?? The test output will be ambiguous.
    It should_be_true = () =>
        value.ShouldBeTrue();
}

Test classes should be Snake_cased

The test class should begin with When and be Snake_cased

Right:

class When_using_a_car
{
}

Wrong:

class 

Fields in a context should be snake_cased

Right:

class When_using_a_car
{
    static Car car;
    static bool is_stopped;
}

Wrong:

class When_using_a_car
{
    static Car _car;
    static bool isStopped;
}

Formatting

Do not use visibility modifiers

The only exception to this is for behaviors, where a protected property is used to mimic behavior (see Behaviors).

Right:

class When_using_a_car
{
    static bool value;

    It should_be_true = () =>
        value.ShouldBeTrue();
}

Wrong:

public class When_using_a_car
{
    private static bool value;

    private It should_be_true = () =>
        value.ShouldBeTrue();
}

Put lambda expressions on new line

Right:

 It should_be_true = () =>
    value.ShouldBeTrue();

Wrong:

It should_be_true = () => value.ShouldBeTrue();

Do not use braces for single-line lambdas

Right:

 It should_be_true = () =>
    value.ShouldBeTrue();

Wrong:

It should_be_true = () =>
{
    value.ShouldBeTrue();
};

Fields should appear first in a class

Right:

class When_using_a_car
{
    static bool value;

    It should_be_true = () =>
        value.ShouldBeTrue();
}

Wrong:

class When_using_a_car
{
    It should_be_true = () =>
        value.ShouldBeTrue();

    static bool value;
}
Clone this wiki locally