-
Notifications
You must be signed in to change notification settings - Fork 178
Best Practices
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))]
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. A good rule of thumb is to nest no more than 2 or 3 classes deep in your tests.
Consider the following plain-text specification: When driving a car and the car moves forward and radio is on, upon reaching a traffic light, the car stops
. This statement could necessitate 3 nested classes and really stretches the limit of a sensible English grammar!
Right:
class When_driving_a_car
{
Establish context = ... ;
class when_the_car_moves_forward
{
Establish context = ... ;
}
}
The Behaviors
feature is only maintained for backwards compatibility, and usage is discouraged for the following reasons:
- No strong typing between behavior subjects hides the fact that the wrong type may have been used
- No compilation checking of the behavior subject
- ReSharper has issues with behaviors and places duplicate gutter marks for tests
Right:
It should_turn_off_engine = () =>
stopped.ShouldBeTrue();
Wrong:
It should_turn_off_engine = () =>
{
var stopped = car.Stop();
stopped.ShouldBeTrue();
}
Right:
Because of = () =>
car.StartEngine();
Wrong:
Because of = () =>
{
car = new Car();
var key = new Key();
car.StartEngine(key);
}
Establish
is for arrange, Because
is for acting, and It
should be used for asserting.
Tests should roughly follow language grammar and should read with/when such a state, when something happens, it should be xyz
.
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();
}
The test class should begin with a conjunction such as when
, and be snake_cased
.
Right:
class When_using_a_car
{
}
Wrong:
class WhenUsingACar
{
}
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;
}
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();
}
Recommended:
It should_be_true = () =>
value.ShouldBeTrue();
Right:
It should_be_true = () =>
value.ShouldBeTrue();
Wrong:
It should_be_true = () =>
{
value.ShouldBeTrue();
};
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;
}
Getting Started
Test Runners
Guidelines