BDD Integration Tests

Having played with a few of the BDD Frameworks out there, we decided to go with StoryQ [http://storyq.codeplex.com/]. We looked at SpecFlow (SF) as well but had major difficulties in getting it to play nice with our “transactional pattern” for dealing with data setup per test.

We basically initiate a transaction (TransactionScope) in our tests, in which we perform data setup, and run the test. The transaction never gets committed so data changes are automatically rolled back, avoiding collisions with other tests. I do not want to move away from this pattern as it’s very effective and easy to understand and bootstrap into some basic infrastructure.

StoryQ does not create a huge abstraction away from the underlying test infrastructure like SF does. With SF you are writing to Cucumber spec and and it generates the test fixture and the related scenario file for you. You don’t deal directly with the tests themselves which was where our problem was realised. There are hooks for performing actions at various stages of the test lifecycle but nothing that enabled us to initiate a discrete transaction per test. So, no go.

StoryQ lives in your own test fixture, so you can do whatever you want. You define the test using the preferred Given-When-Then structure which is made possible with a neat little fluent interface exposed by StoryQ:

[Test]
public void AddSlide()
{
    using (TransactionScopeHelper.Transaction())
    {
        new Story(“Add Slide to Case”)
            .InOrderTo(“Add a slide to a case”)
            .AsA(“Valid User”)
            .IWant(“The slide to be added to the case”)
            .WithScenario(“A valid slide”)
            .Given(ValidSlideDetailsAreEntered)
            .When(TheAddSlideButtonIsPressed)
            .Then(TheSlideShouldBeAddedToTheCase)
            .ExecuteWithReport(MethodBase.GetCurrentMethod());
    }
}

Your outcome assertions are in the function called when .Then is executed; too easy. You can place assertions into the Given and When steps as required.

You also get the pretty output which reads like English and can be given to testers / domain experts for validation:

Story is Delete Slide from Case
  In order to Delete a slide from a case
  As a Valid User
  I want The slide to be removed from to the case

      With scenario A valid unprocessed slide
        Given an unprocessed slide is selected    => Passed
        When the delete slide button is pressed   => Passed
        Then the slide should be deleted          => Passed

 

We have structured the tests like this:

Integration Test Project

   –> Stories

       –> Folder For Story

           –> File for each scenario

image