Practical ASP.NET

Stepping Through Binding Styles Using SpecFlow 2

SpecFlow offers a number of binding styles for bridging business-readable tests with test-automation code.

SpecFlow allows the building of a bridge between the business and the development team by allowing the creation of business-readable tests. It does this by allowing the writing of high-level scenarios written in natural language (English, French, German and so on).

SpecFlow scenarios are written in this high-level language that business people, clients and other stakeholders can understand. On their own, the steps in a scenario cannot be executed as tests; they need to be "bound" to test-automation code.

SpecFlow provides a number of binding styles.

In Listing 1, each step in the "Add two numbers" scenario maps ("binds") to a C# method. It's inside these bound C# methods that the automation code is added. It's also worth noting that a single C# method can map to multiple lines (steps) in the scenarios; this allows code reuse and reduces test code maintenance overheads.

Listing 1: A Simple SpecFlow Feature
Feature: Calculator
     In order to make it easier on my brain
     As someone who is not good at mental arithmetic
     I want to use the computer to do basic maths

Scenario: Add two numbers
     Given The calculator is reset 	
     When I enter 40
       And I Add 20
     Then The value should be 60

To generate an initial steps class that contains C# methods representing the scenario steps, the SpecFlow Visual Studio IDE integration can be used. To accomplish this, right-click in the feature file and in the context menu, and choose Generate Step Definitions as shown in Figure 1.

[Click on image for larger view.] Figure 1. Generating Step Definitions

A dialog box will now appear with a number of options as shown in Figure 2.

[Click on image for larger view.] Figure 2. Generating Steps Definition Dialog Box

Notice that one of the options here is the ability to select a steps binding style as shown in Figure 3.

[Click on image for larger view.] Figure 3. Binding Style Selection

Regular Expression Binding Style
The default binding style is the regular expression style. This style uses attributes on C# methods to map them to scenario steps.

Listing 2 shows a generated feature file using the regular expression style for the scenario shown in Listing 1.

Listing 2: Regular Expression Binding
using System;
using TechTalk.SpecFlow;

namespace SpecFlow2Demo
{
  [Binding]
  public class CalculatorSteps
  {
    [Given(@"The calculator is reset")]
    public void GivenTheCalculatorIsReset()
    {
      ScenarioContext.Current.Pending();
    }
        
    [When(@"I enter (.*)")]
    public void WhenIEnter(int p0)
    {
      ScenarioContext.Current.Pending();
    }
        
    [When(@"I Add (.*)")]
    public void WhenIAdd(int p0)
    {
      ScenarioContext.Current.Pending();
    }
        
    [Then(@"The value should be (.*)")]
    public void ThenTheValueShouldBe(int p0)
    {
      ScenarioContext.Current.Pending();
    }
  }
}

Notice in Listing 2 the additional SpecFlow binding attributes applied to the individual methods: [Given], [When], and [Then]. Each of these attributes takes a regular expression as a parameter. If this regular expression matches the text in a scenario step it will be bound to that step.

If the scenario step contains a parameter that needs to be passed to the bound C# method, this can be captured in the regular expression. For example, the step, "When I enter 40," can be reused with different data by making the "40" a parameter that is passed to the C# method. In the regular expression binding style, this parameter can be captured: "I enter (.*)")]. Here, the regular expression (.*) will capture the text "40" and pass it to the method for use in the automation code.

Method Name Underscore Style
The second binding style is the method name underscore style. This style still has attributes applied to methods, but rather than a regular expression doing the matching, the method name itself is used.

Listing 3 shows an example of the underscore style for the scenario in Listing 1.

Listing 3: Underscore-Style Binding
using TechTalk.SpecFlow;

namespace SpecFlow2Demo
{
  [Binding]
  public class CalculatorSteps
  {
    [Given]
    public void Given_The_calculator_is_reset()
    {
      ScenarioContext.Current.Pending();
    }
        
    [When]
    public void When_I_enter_P0(int p0)
    {
      ScenarioContext.Current.Pending();
    }
        
    [When]
    public void When_I_Add_P0(int p0)
    {
      ScenarioContext.Current.Pending();
    }
        
    [Then]
    public void Then_The_value_should_be_P0(int p0)
    {
      ScenarioContext.Current.Pending();
    }
  }
}

Notice in Listing 3 that the name of the method itself matches the text in the scenario. For example, the step text, "Given The calculator is reset," maps directly to the method, "public void Given_The_calculator_is_reset()." Underscores are used here to separate words.

Parameters in the underscore style are mapped by using uppercase tokens. By default these use the P0, P1 and so on style. A custom token name can also be used; Listing 4 shows two ways the "And I Add 20" step can be bound.

Listing 4: Underscore-Style Parameter Passing
[When]
public void When_I_Add_P0(int p0)
{
  // Test code here
}

[When]
public void When_I_Add_NUMBER(int number)
{
  // Test code here
}

Notice in the second method, the method parameter ("number") matches the uppercase token NUMBER in the method name.

Method Name Pascal Case Binding Style
The Pascal case binding style is very similar to the method name underscore style, but rather than underscores separating words, Pascal casing is used instead. Listing 5 shows this style.

Listing 5: Pascal Case Binding Style
using TechTalk.SpecFlow;

namespace SpecFlow2Demo
{
  [Binding]
  public class CalculatorSteps
  {
    [Given]
    public void GivenTheCalculatorIsReset()
    {
      ScenarioContext.Current.Pending();
    }
        
    [When]
    public void WhenIEnter_P0(int p0)
    {
      ScenarioContext.Current.Pending();
    }
        
    [When]
    public void WhenIAdd_P0(int p0)
    {
      ScenarioContext.Current.Pending();
    }
        
    [Then]
    public void ThenTheValueShouldBe_P0(int p0)
    {
      ScenarioContext.Current.Pending();
    }
  }
}

Just as with the underscore style, parameters are represented as tokens, with either P0, P1 and so on, or named tokens.

About the Author

Jason Roberts is a Microsoft C# MVP with over 15 years experience. He writes a blog at http://dontcodetired.com, has produced numerous Pluralsight courses, and can be found on Twitter as @robertsjason.

comments powered by Disqus

Featured

  • How to Do Machine Learning Evolutionary Optimization Using C#

    Resident data scientist Dr. James McCaffrey of Microsoft Research turns his attention to evolutionary optimization, using a full code download, screenshots and graphics to explain this machine learning technique used to train many types of models by modeling the biological processes of natural selection, evolution, and mutation.

  • Old Stone Wall Graphic

    Visual Studio Code Boosts Java Dependency Viewer

    Easier management of project code dependencies and improvements to extensions for popular Java frameworks and runtimes highlight the February update to Java in Visual Studio Code functionality.

  • Blule Squares

    Visual Studio 2019 for Mac 8.5 Preview Adds ASP.NET Core Authentication

    Microsoft, after shipping Visual Studio 2019 for Mac v8.4 with support for ASP.NET Core Blazor Server applications last month, is now previewing the v8.5 series, adding new authentication templates for ASP.NET Core along with other improvements.

  • Q&A with Brice Wilson: What's New in Angular 9

    We caught up with expert web developer/trainer Brice Wilson to get his take on Angular, which always appears at or near the top of periodic rankings of the most popular JavaScript-based web development frameworks.

  • Entity Framework Core Migrations

    Eric Vogel uses code samples and screenshots to demonstrate how to use Entity Framework Core migrations in a .NET Core application through the command line and in code.

.NET Insight

Sign up for our newsletter.

Terms and Privacy Policy consent

I agree to this site's Privacy Policy.

Upcoming Events