Use when a .NET project starts BDD, migrates from SpecFlow (end-of-life 2024-12-31) or maintains a legacy SpecFlow suite. Configures Reqnroll: Gherkin .feature files, [Given/When/Then] C# bindings, hooks and dotnet test runs.
89%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
The canonical home for this skill is testland/reqnroll-testing
Per reqnroll-home:
"Reqnroll is described as 'an open-source Cucumber-style BDD test automation framework for .NET. It has been created as a reboot of the SpecFlow project.'"
The "reboot" framing is the key: SpecFlow's maintenance slowed in 2023; the community forked into Reqnroll, which has continued active development.
For SpecFlow-locked legacy projects mid-migration (packages, bindings, EOL background), see references/specflow-legacy.md.
A checkout team adds one BDD scenario, "Apply valid promo," to a new xUnit project.
dotnet add package Reqnroll.xUnit and
dotnet add package Reqnroll.Tools.MsBuild.Generation.Features/Cart.feature declares the scenario under
Rule: Promo codes apply only when valid, with
When I enter "WELCOME10" in the promo input / Then the subtotal updates to $22.49.Steps/CartSteps.cs binds each line - [When(@"I enter ""([^""]*)"" in the promo input")] calls _page.EnterPromoAsync(code), and the Then asserts
Assert.Equal(22.49m, _page.GetSubtotal(), 2).dotnet test --filter "FullyQualifiedName~Cart" runs only that feature..feature file - no glue code beyond the
bindings.# In the test project directory
dotnet add package Reqnroll.xUnit # or Reqnroll.NUnit / Reqnroll.MsTest
dotnet add package Reqnroll.Tools.MsBuild.Generation # generates code from .feature filesPer reqnroll-home: "Works across common operating systems and .NET versions (including .NET 8.0)."
Verify: dotnet build succeeds and restores both packages before you
author features. If code generation does not run, confirm
Reqnroll.Tools.MsBuild.Generation is referenced in the test project.
# Features/Cart.feature
Feature: Apply promo code at checkout
Background:
Given a logged-in user with email confirmed
And the cart contains 1 of "BOOK-001" at $24.99
Rule: Promo codes apply only when valid
Scenario: Apply valid promo
When I enter "WELCOME10" in the promo input
And I click "Apply"
Then the subtotal updates to $22.49
Scenario Outline: Reject invalid codes
When I enter "<code>" in the promo input
And I click "Apply"
Then an error appears: "<error>"
Examples:
| code | error |
| EXPIRED50 | This code has expired |
| NOTREAL | Code not found |Rule: blocks (Gherkin 6+) group related scenarios; per
reqnroll-home this is supported.
Write step bindings as [Given/When/Then]-decorated methods in a [Binding]
class. Per reqnroll-home: "Supports flexible step definitions using regex
or cucumber expressions" - regex is more flexible, cucumber expressions
({int}, {string}, {double}) more readable. Full CartSteps binding class
and the cucumber-expression variant:
references/bindings-and-hooks.md.
Per reqnroll-home: "Async step definitions and hooks."
[Then("the order arrives within (\\d+) minutes")]
public async Task ThenOrderArrives(int minutes)
{
await EmailInbox.WaitForOrderConfirmation(TimeSpan.FromMinutes(minutes));
}async Task step methods work transparently; no special config.
Use [BeforeTestRun], [BeforeScenario] / [AfterScenario], and tag-scoped
hooks (e.g. [BeforeScenario("@browser")]) for setup and teardown; wrap each
scenario in a transaction and roll back in [AfterScenario] so state does not
leak between scenarios. Full hook class:
references/bindings-and-hooks.md.
@critical @regression
Scenario: Apply valid promo
...
@browser @wip
Scenario: New checkout flow
...dotnet test --filter "Category=critical"
dotnet test --filter "Category!=wip"# All tests
dotnet test
# Specific feature
dotnet test --filter "FullyQualifiedName~Cart"
# Generate JUnit XML for CI
dotnet test --logger "junit;LogFilePath=reports/test-results.xml"If a scenario fails or reports an undefined step, fix the matching binding in
the [Binding] class and re-run until it turns green.
Per reqnroll-home: "IDE support for Visual Studio 2022, VS Code, and Rider."
The Reqnroll plugin enables:
Per reqnroll-home: "Compatible with SpecFlow, allowing quick migration of existing projects."
Migration path:
SpecFlow.* NuGet packages with Reqnroll.* equivalents.using SpecFlow → using Reqnroll (single find/replace).[Binding] (compatible) and step decorators (mostly
compatible).Most SpecFlow projects migrate in <1 day for typical scope.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Starting new .NET BDD with SpecFlow in 2026+ | SpecFlow's maintenance has slowed; Reqnroll is the active fork. | Pick Reqnroll (Step 1). |
| Mixing SpecFlow + Reqnroll in one solution | Two BDD runners; double maintenance. | Migrate everything (Step 9). |
| Regex-only steps when cucumber expressions would work | Less readable; harder to maintain. | Cucumber expressions for typical cases (Step 3). |
No [BeforeScenario] cleanup | State leaks between scenarios. | Per-scenario hook + transaction rollback (Step 5). |
| Sync step methods that block on async | Deadlocks in xUnit / NUnit / MsTest. | async Task step methods (Step 4). |
cucumber-testing,
behave-testing - sibling language
wrappers.bdd-step-library-curator - addresses step proliferation.testland/qa
aa16752
Canonical home
since Jul 23, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.