The documentation on SpecsFor is sorely lacking.  Me (and another volunteer!) are working to fix that.  This is part of a series of posts about SpecsFor, which will eventually make its way in to the official docs.

In our last post, we looked at organizing specs in a typical web project.  We created two projects to house our specs, and we added SpecsFor to each of them using NuGet.  In this post, we’ll shift gears and focus on the mechanics of testing as we create our first spec!

[more]

image

Writing specs for ASP.NET MVC introduces a few “wrinkles” that we’re not ready to tackle yet, so we aren’t going to start there.  Instead, we’ll write specs for a much simpler class.  Let’s start by looking at the code we’re going to test.  It’s a simple object representing an automobile:

public class Automobile
{
    public AutomobileState State { get; set; }

    public StartResult Start()
    {
        bool successful = false;

        if (State == AutomobileState.Stopped)
        {
            State = AutomobileState.Running;
            successful = true;
        }

        return new StartResult
        {
            Successful = successful,
            State = State
        };
    }
}

NOTE: For anyone that’s screaming about TDD already: for the sake of simplicity, we are intentionally doing Test-After-Development.  We’ll come back to TDD in a future post. 

It’s pretty obvious what the code is doing, but let’s describe it at a high level.  When we try to start the automobile, the car will start only if it is currently stopped.  Let’s try to back this up a step, and think about a specification that might describe this behavior:

Given the automobile is stopped, when we start it, then the car starts.

This specification follows a simple structure.  Look at it again:

Given the automobile is stopped…

When we start it…

Then the car starts.

Given, When, Then.  This pattern is the one SpecsFor implements.

Given, When, Then vs. Arrange, Act, Assert

There are two common vocabularies that people use when describing their specifications or tests.  The more "traditional" way is called Arrange, Act, Assert. You arrange things into the state you want them in before you begin your test.  Then, you act on the class or system under test (in the example above, our automobile would be our system under test, and calling the Start method is our act).  Finally, you assert that the world is the way you expect it.  For the example above, we would want to make sure the automobile starts, so we would assert that state is now “Running”.  We also would expect the Start method to return a successful result, so we’d assert that as well.

So, that’s the Arrange, Act, Assert vocabulary.  It has fallen out of favor for various reasons, giving way to the the Given, When, Then vocabulary.  The two are equivalent, but the later translates nicely to English-like specs, where as the former sounds a bit obtuse when you try to use it to create human-readable specs. 

SpecsFor was built with the Given, When, Then vocabulary in mind.  It provides hooks for you to establish context (Given…), perform an action, (When…), and by convention most people name their individual test cases with Then as a prefix. 

Enough talk, let’s create a spec!

The First Spec

There are easier ways to create a spec with SpecsFor, but for now, let’s do things the “hard” way.  We’ll start by creating a new class in our unit specs project.  Let’s name the class "AutomobileSpecs."  This will give us an empty class.  We are not going to create any specs directly within this class.  This class is going to serve as a wrapper for our specs.  We’ll nest additional spec classes within this class for each scenario we want to test.  It may feel a little odd, and this nesting isn’t required, but there’s a good reason for it, as we’ll see soon. 

For now, let’s add a using statement to import SpecsFor, another for our automobile, then let’s create our actual spec for the scenario above, which we’ll call “when starting an automobile.”  We can’t put spaces in our class name though, so we’ll replace the spaces with underscores, like so: when_starting_an_automobile.  Our spec will derive from SpecsFor’s base class, SpecsFor<T>, and we’ll substitute the class we want to test for the type parameter.  That means we’ll actually inherit from SpecsFor<Automobile>.  At this point, we’ve got something like this:

using Sample3.Core;
using SpecsFor;

namespace Sample3.UnitSpecs.Core
{
    public class AutomobileSpecs 
    {
        public class when_starting_an_automobile : SpecsFor<Automobile>
        {
            
        }
    }
}

Congrats, you now have a spec class!  And this spec is already doing quite a bit even though we’ve only defined a couple of classes.  It’s already creating an instance of Automobile to write our tests against.   It’s stored in a property called “SUT,” which stands for “System Under Test.”  You can access it from any of your specs, like so:

public void then_the_engine_is_started()
{
    SUT.State.ShouldEqual(AutomobileState.Running);
}

If Automobile had any dependencies (specified using constructor arguments as is typical with constructor injection), those would be provided as well, and we could retrieve them to configure behavior and verify interactions.

And SpecsFor is also checking to see if Automobile implements IDisposable.  If it does, it’ll be cleaned up automatically when any tests we’ve defined within our spec have finished executing.  

That’s it for this post.  In the next post, we’ll actually create some test cases within our spec!