SpecFlow for .NET — BDD in C# with Visual Studio Integration

SpecFlow (now succeeded by Reqnroll in the open-source community) brings BDD to the .NET ecosystem. It integrates with Visual Studio, generates step definition bindings from feature files, and runs scenarios using NUnit or xUnit as the test runner. For teams working in C# with ASP.NET Core, SpecFlow provides the same Gherkin-driven workflow as Cucumber, with .NET-native tooling and Selenium WebDriver integration.

SpecFlow — BDD in the .NET Ecosystem

SpecFlow follows the same Gherkin → Step Definitions → Automation pattern as Cucumber, but with C# syntax and .NET project conventions.

// ── Feature File: Features/Login.feature ──
// (Same Gherkin syntax as Cucumber — .feature files are universal)

/*
Feature: User Login
  Scenario: Successful login
    Given I am on the login page
    When I enter username "standard_user" and password "secret_sauce"
    And I click the login button
    Then I should see the inventory page
*/


// ── Step Definitions: StepDefinitions/LoginSteps.cs ──

using TechTalk.SpecFlow;  // or Reqnroll
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using NUnit.Framework;

[Binding]
public class LoginSteps
{
    private IWebDriver _driver;

    [BeforeScenario]
    public void Setup()
    {
        _driver = new ChromeDriver();
        _driver.Manage().Window.Maximize();
    }

    [AfterScenario]
    public void Teardown()
    {
        _driver.Quit();
    }

    [Given("I am on the login page")]
    public void GivenIAmOnTheLoginPage()
    {
        _driver.Navigate().GoToUrl("https://www.saucedemo.com");
    }

    [When(@"I enter username ""(.*)"" and password ""(.*)""")]
    public void WhenIEnterCredentials(string username, string password)
    {
        _driver.FindElement(By.Id("user-name")).SendKeys(username);
        _driver.FindElement(By.Id("password")).SendKeys(password);
    }

    [When("I click the login button")]
    public void WhenIClickTheLoginButton()
    {
        _driver.FindElement(By.Id("login-button")).Click();
    }

    [Then("I should see the inventory page")]
    public void ThenIShouldSeeTheInventoryPage()
    {
        Assert.That(_driver.Url, Does.Contain("inventory"));
    }
}


// ── Project Setup ──

/*
  1. Create a new NUnit or xUnit test project:
     dotnet new nunit -n ShopTests

  2. Install SpecFlow (or Reqnroll) packages:
     dotnet add package SpecFlow.NUnit
     dotnet add package SpecFlow.Tools.MsBuild.Generation
     dotnet add package Selenium.WebDriver
     dotnet add package Selenium.WebDriver.ChromeDriver

  3. Add .feature files to a Features/ folder
  4. Right-click a .feature step → "Generate Step Definitions" (VS extension)
  5. Run: dotnet test
*/


// ── SpecFlow vs Reqnroll ──

/*
  SpecFlow was the dominant .NET BDD tool for 10+ years.
  In 2023, SpecFlow's commercial owner (Tricentis) reduced open-source support.
  Reqnroll is the community fork that continues SpecFlow's open-source mission.

  For new projects: consider Reqnroll (same API, same Gherkin, active community).
  For existing projects: SpecFlow continues to work; migration to Reqnroll is minimal.
*/
Note: SpecFlow’s Visual Studio extension provides a critical productivity feature: right-click any Gherkin step in a .feature file and select “Generate Step Definitions” to auto-generate the C# binding method with the correct attribute, parameter extraction, and method signature. This eliminates the manual work of writing regex patterns and matching parameter types. The generated code is a skeleton — you fill in the automation logic.
Tip: Use SpecFlow’s Dependency Injection (with the SpecFlow.Autofac or SpecFlow.Microsoft.Extensions plugin) to inject page objects and WebDriver instances into step definition classes. This eliminates manual driver management and follows .NET best practices for dependency injection. Step classes receive their dependencies through constructors, making them testable and decoupled from specific WebDriver implementations.
Warning: SpecFlow generates a code-behind file (.feature.cs) from each .feature file. This file must be regenerated when the feature file changes. If the auto-generation fails (missing NuGet package, build error), the step bindings break silently. Always verify that SpecFlow.Tools.MsBuild.Generation is installed and that the project builds clean before debugging binding issues.

Common Mistakes

Mistake 1 — Not using SpecFlow’s step definition generator

❌ Wrong: Manually typing step definition attributes and regex patterns — error-prone and slow.

✅ Correct: Right-clicking the Gherkin step in Visual Studio and selecting “Generate Step Definitions” — auto-generates the binding with correct regex and parameter extraction.

Mistake 2 — Creating a new WebDriver in every step definition class

❌ Wrong: Each step definition class creates its own ChromeDriver() — multiple browser windows open during one scenario.

✅ Correct: Using SpecFlow’s context injection or a [BeforeScenario] hook to create one driver per scenario, shared across all step definition classes via context.

🧠 Test Yourself

What is the relationship between SpecFlow and Reqnroll?