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

  • Hands On: New VS Code Insiders Build Creates Web Page from Image in Seconds

    New Vision support with GitHub Copilot in the latest Visual Studio Code Insiders build takes a user-supplied mockup image and creates a web page from it in seconds, handling all the HTML and CSS.

  • Naive Bayes Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the naive Bayes regression technique, where the goal is to predict a single numeric value. Compared to other machine learning regression techniques, naive Bayes regression is usually less accurate, but is simple, easy to implement and customize, works on both large and small datasets, is highly interpretable, and doesn't require tuning any hyperparameters.

  • VS Code Copilot Previews New GPT-4o AI Code Completion Model

    The 4o upgrade includes additional training on more than 275,000 high-quality public repositories in over 30 popular programming languages, said Microsoft-owned GitHub, which created the original "AI pair programmer" years ago.

  • Microsoft's Rust Embrace Continues with Azure SDK Beta

    "Rust's strong type system and ownership model help prevent common programming errors such as null pointer dereferencing and buffer overflows, leading to more secure and stable code."

  • Xcode IDE from Microsoft Archrival Apple Gets Copilot AI

    Just after expanding the reach of its Copilot AI coding assistant to the open-source Eclipse IDE, Microsoft showcased how it's going even further, providing details about a preview version for the Xcode IDE from archrival Apple.

Subscribe on YouTube

Upcoming Training Events