Behavioural testing in .Net with SpecFlow and Selenium (Part 1)

In this series of posts I am going to run through using Selenium and SpecFlow to test .Net applications via the user interface. I will talk about the situations this type if testing can be used, and how we can create effective, non-brittle test with the help of the Page Objects Pattern.

The series in full:

I have consciously avoided using the term Behaviour Driven Development (BDD) in the title as this post isn’t really about BDD as such. It is about using some tools in a way that could be used in many situations, with BDD being just one of them. I want to discuss how to use the BDD Framework SpecFlow and the web automation framework Selenium to create tests that test an application via it’s web user interface.

When to use this approach

You could use this approach in several situations. In any situation the idea is to create an executable specification and create automated testing for your code base. The two most common situations are:

  1. Automated acceptance tests – lets call this approach ‘test afterwards’. There is often a desire to create acceptance tests (or integration tests or smoke tests or whatever…) for an application. Using SpecFlow and Selenium you can create tests that test the application as a user would actually interact with it. A suite of acceptance tests is a worthwhile addition to any application.
  2. Behaviour Driven Development style – This is the ‘test before’ approach. In Test Driven Development with MVC I talked about how a true BDD style would ideally test user interaction with the application. These tools allow you to do just that. The workflow would be very similar to the outside-in approach I describe in the post, only you would create scenarios in SpecFlow instead of writing unit tests. Of course there are tons of approaches when it comes to BDD, this being  just one of them. Liz Keogh has a useful summary and introduction to BDD that is worth a look if you want to know more about it.

In this post I am going to use a test afterwards approach so that I can focus on the tooling.

Installing SpecFlow and Selenium

I have created a new folder to house my acceptance tests. Installing Selenium is easy, simply grab the latest version from NuGet (you are using NuGet, right?). Make sure to select Selenium WebDriver. For SpecFlow grab the latest version from NuGet and then get the Visual Studio integration from the Visual Studio Gallery. This will add some extra VS tooling we will use later.

The first scenario

I am going to revisit the event search scenario’s from Test Driven Development with MVC and expand on them a little. The first thing is to add a SpecFlow feature file to the project. Right click on the project and select New item.. Add a new SpecFlow feature file. I have called mine EventSearch.feature. The feature file has feature,which is essentially a user story, and a number of scenarios in the Given When Them format.

The feature files are written in the Gherkin language, which is intended to be a human readable DSL for describing business behaviour.

Lets start populating the feature file with the first scenario.

Feature: EventSearch
	In order to find an event to participate in
	As a potential event delegate
	I want to be able to search for an event

Scenario: Event Search Criteria should be displayed
	Given that I want to search for an event by region
	When I select to choose a region
	Then a list of possible regions is presented
	And the list should contain "All", "North", "South" and "London"
	And "All" should be the default value

The next step is to create the bindings that allows us to wire up the Gherkin feature to our application’s code. Before we do that we just need to tell SpecFlow to use Visual Studio’s testing framework MSTest instead of the default NUnit. This is done by adding a line  of configuration to your app.config, you will find the SpecFlow section already exists:

<specFlow>
<!-- For additional details on SpecFlow configuration options see http://go.specflow.org/doc-config -->

    <unitTestProvider name="MsTest.2010"/>
</specFlow>

As a brief aside, you will notice that the feature file has a code behind .cs file that has been created by SpecFlow. If you have a look inside you will see that the code is a rather awkward looking MSTest test class. It is used to run the Scenario’s that are described in the feature file and implemented in the binding step definitions we are about to create. It is not pretty, but it is not intended to be read or edited by a user as it is generated by SpecFlow when the feature file is saved. SpecFlow will generate the correct type of testing hooks for the test framework you are using.

Create the step definitions

The step definitons are where we add code to perform the tests. The step defintions are defined in a file with a [Binding] attribute. When we run the feature the test runner run the test defined in the feature code-behind which is bound to these steps by SpecFlow. The easiest way to create these bindings is to use SpecFlows Visual Studio tooling. Right click on the scenario in the feature file and select “Generate step definitions”. This brings up a dialogue box that allows you to create the necessary bindings to wire up the test. I created the bindings in a new class called EventSearchSteps. The generated bindings look like this:

using System;
using TechTalk.SpecFlow;

namespace CrazyEvents.AcceptanceTests
{
    [Binding]
    public class EventSearchSteps
    {
        [Given(@"that I want to search for an event by region")]
        public void GivenThatIWantToSearchForAnEventByRegion()
        {
            ScenarioContext.Current.Pending();
        }

        [When(@"a list of possible regions is presented")]
        public void ThenAListOfPossibleRegionsIsPresented()
        {
            ScenarioContext.Current.Pending();
        }

        [Then(@"the list should contain ""(.*)"", ""(.*)"", ""(.*)"" and ""(.*)""")]
        public void ThenTheListShouldContainAnd(string p0, string p1, string p2, string p3)
        {
            ScenarioContext.Current.Pending();
        }

        [Then(@"""(.*)"" should be the default value")]
        public void ThenShouldBeTheDefaultValue(string p0)
        {
            ScenarioContext.Current.Pending();
        }
    }
}

The step definitions have been created with a pending implementation ready for us to complete. You will see that some parts of the features have generated steps that contains attributes with what looks like regular expressions, and that the methods have parameters. This is a feature of SpecFlow that allows for reuse of step definitions when the only thing that changes is a string value. We will see how this is used later. SpecFlow has lots of useful features like this, I would advise checking out the documentation to learn more about it.

Lets run the test and see what happens.

Resharper’s test runner shows that the test was inconclusive. This is not really a surprise as the test implementation is pending. Of course you can use Visual Studio’s built in test runner instead.

In the next post we will have a look at how we can implement the bindings with Selenium to automate browser interactions.

The series in full:

Advertisements

6 Responses to Behavioural testing in .Net with SpecFlow and Selenium (Part 1)

  1. Pingback: Behavioural testing in .Net with SpecFlow and Selenium (Part 2) « James Heppinstall: On Development

  2. Pingback: A Smattering of Selenium #124 « Official Selenium Blog

  3. Pingback: The easy way to runSelenium and SpecFlow tests in a TeamCity build with IIS Express « James Heppinstall: On Development

  4. Pingback: Managing SpecFlow acceptance test data with Entity Framework « James Heppinstall: On Development

  5. Pingback: Getting started with automated acceptance tests in an Agile project | James Heppinstall: On Development

  6. Pingback: Confluence: Team Service Manager

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: