I’m fan of specification style testing. I’ve used mspec on my own projects and have been really happy with it. I would use it at work too, however, most developers I have/are working with have never heard of it let along used it. I would say all these developers have used a xUnit like test framework and if I was to guess which one it would be NUnit. It would be unreasonable of me to force everyone to switch to mspec just because I like it. Also, there is a slight learning curve – when developers already complain that writing tests slow them down, I don’t want them to slow them down further. (There are other reasons too, but I don’t want to go into those.)
So how can we write specification style tests using the tools we already have? Simple, use one test class per test:
public class When_I_initialize_People_with_text
{
private People people;
public When_I_initialize_People_with_text()
{
people = new People { "{\"firstName\":\"John\",
\"lastName\":\"Smith\"}" };
}
[Fact]
public void It_should_contain_expected_number_of_items()
{
people.Count().Should().Be(1);
}
[Fact]
public void It_should_contain_expected_person()
{
people.First().ShouldBeEquivalentTo(
new Person("John", "Smith"));
}
}
I’m using xUnit 2 in the example above but that’s because I prefer it over NUnit. With xUnit there is just one attribute to remember and the setup/teardown is much simpler.
The test class does one thing – its written on the tin. The assertions, too, are clear. You might not approve of the underscores, but I think its easier to read than using PascalCase.
This pattern is fine for most cases, but what if your setup/teardown parts are slow, for example, seeding a database with some test data. You have to use class fixtures.
public class When_I_initialize_People_with_text_that_includes_invalid_data
: IClassFixture
{
public class Context : Context
{
public Context()
{
SUT = new People {
"{\"firstName\":\"John\", " +
"\"lastName\":\"Smith\"}",
"{\"member\":\"John\", " +
"\"another_member\":\"Smith\"}"
};
}
}
private People people;
public When_I_initialize_People_with_text_that_includes_invalid_data(Context context)
{
people = context.SUT;
}
[Fact]
public void It_should_contain_expected_number_of_items()
{
people.Count().Should().Be(1);
}
[Fact]
public void It_should_contain_expected_person()
{
people.First().ShouldBeEquivalentTo(
new Person("John", "Smith"));
}
}
Its not quite as readable, but its not bad. (There is an alternative – I’ll save it for a future post.)
Code samples can be found here: Specification Test Patterns