A powerful Reqnroll generator plugin that enables calling and embedding scenarios from other feature files directly within your test scenarios. This plugin promotes test reusability, modularity, and better organization of your Gherkin specifications.
- 🔄 Scenario Reusability: Call existing scenarios from any feature file
- 🎯 Inline Expansion: Automatically expands scenario calls during test generation
- 🗂️ Cross-Feature Support: Reference scenarios across different feature files
- 📄 Same-Feature Calls: Call scenarios within the same feature file ✨ NEW!
- 🚀 Cross-Project Support: Automatically discovers and calls scenarios from referenced projects
- 🏗️ Build-Time Processing: No runtime overhead - scenarios are expanded at build time
- 🛡️ Error Handling: Missing scenarios and features fail with clear diagnostics
- 🧭 Generated Call Markers: Generated tests show when another scenario is being called
- 🔒 Recursion Detection: Automatically prevents circular scenario references ✨ NEW!
- 📁 Automatic Discovery: Automatically finds feature files in referenced projects - no manual copying needed
- 🌍 Multi-Language Support: Supports all Gherkin languages (English, German, French, Spanish, Dutch, and more)
Use the following syntax to call scenarios from other features:
Given I call scenario "ScenarioName" from feature "FeatureName"
When I call scenario "ScenarioName" from feature "FeatureName"
Then I call scenario "ScenarioName" from feature "FeatureName"
And I call scenario "ScenarioName" from feature "FeatureName"
But I call scenario "ScenarioName" from feature "FeatureName"To include Background steps from the target feature, add with background:
Given I call scenario "ScenarioName" from feature "FeatureName" with backgroundNote: By default, scenario calls do NOT include Background steps from the target feature. Use the with background syntax when you need the Background steps to be executed.
See the examples folder for complete working examples:
- examples/BasicUsage - Feature file examples showing the syntax
- examples/MSTestExample - Complete MSTest project example with step definitions
Authentication.feature
Feature: Authentication
As a user
I want to be able to login and logout
So that I can access the application securely
Scenario: Login
Given I am on the login page
When I enter valid credentials
Then I should be logged in successfully
Scenario: Logout
Given I am logged in
When I click the logout button
Then I should be logged outUserManagement.feature
Feature: User Management
As an administrator
I want to manage user accounts
So that I can control access to the system
Scenario: Create New User Account
Given I call scenario "Login" from feature "Authentication"
When I navigate to user management
And I create a new user account
Then the user should be created successfully
And I call scenario "Logout" from feature "Authentication"The scenario call is automatically expanded during build time:
Scenario: Create New User Account
# Expanded from scenario call: "Login" from feature "Authentication"
Given scenario call: "Login" from feature "Authentication"
Given I am on the login page
When I enter valid credentials
Then I should be logged in successfully
When I navigate to user management
And I create a new user account
Then the user should be created successfully
# Expanded from scenario call: "Logout" from feature "Authentication"
And scenario call: "Logout" from feature "Authentication"
Given I am logged in
When I click the logout button
Then I should be logged outThe generated scenario call: step is a no-op marker that is bound by the package. It keeps scenario-call boundaries visible in *.feature.cs files and test runner output without requiring you to add a step definition.
When a target feature has a Background section, you can optionally include it using with background:
Authentication.feature
Feature: Authentication
Background:
Given the authentication system is initialized
And the user database is ready
Scenario: Login
Given I am on the login page
When I enter valid credentials
Then I should be logged in successfullyUserManagement.feature
Feature: User Management
Scenario: Create User with Background
Given I call scenario "Login" from feature "Authentication" with background
When I create a new user account
Then the user should be created successfullyGenerated Output (with background)
Scenario: Create User with Background
# Expanded from scenario call: "Login" from feature "Authentication"
Given scenario call: "Login" from feature "Authentication" with background
# Including Background steps from feature "Authentication"
Given the authentication system is initialized
And the user database is ready
Given I am on the login page
When I enter valid credentials
Then I should be logged in successfully
When I create a new user account
Then the user should be created successfullyNote: If you omit with background, only the scenario steps will be included, and the Background steps will be skipped.
Install the plugin via NuGet Package Manager:
dotnet add package JGerits.Reqnroll.ScenarioCall.GeneratorOr via Package Manager Console in Visual Studio:
Install-Package JGerits.Reqnroll.ScenarioCall.Generator- Download the latest release from the releases page
- Add the assembly reference to your test project
- Ensure the plugin is registered (see Configuration section)
The plugin automatically registers itself with Reqnroll when referenced in your project. No additional configuration is required for basic usage.
The plugin automatically searches for feature files in the following locations relative to your project:
- Current directory
Features/folderSpecs/folderTests/folder
All searches include subdirectories recursively.
MyProject/
├── Features/
│ ├── Authentication.feature
│ ├── UserManagement.feature
│ └── Shopping/
│ ├── Cart.feature
│ └── Checkout.feature
├── Specs/
│ └── Integration/
│ └── EndToEnd.feature
└── Tests/
└── Smoke/
└── SmokeTests.feature
Call scenarios within the same feature file - perfect for sharing common setup or reusable steps without creating separate files!
Example:
Feature: User Management
Scenario: Common Setup
Given the system is initialized
And the database is clean
And test data is loaded
Scenario: Create User With Setup
Given I call scenario "Common Setup" from feature "User Management"
When I create a new user
Then the user should be created successfullyHow it works:
- Reference the current feature by name to call scenarios within the same file
- The plugin automatically detects the current feature context
- Recursion detection prevents infinite loops from self-referencing scenarios
- Works seamlessly with cross-feature calls in the same test
Benefits:
- Reduce duplication within a feature file
- Keep related scenarios organized together
- Avoid creating separate feature files for simple reusable steps
Recursion Protection: The plugin automatically detects and prevents circular references:
Scenario: Self Referencing (Not Allowed)
Given I call scenario "Self Referencing" from feature "User Management"
# Error: Circular reference detected - scenario "Self Referencing" from feature "User Management" is already in the call chainExample: See examples/BasicUsage/SameFeatureCalls.feature for a complete example.
Call scenarios from other projects in your solution - perfect for sharing common test scenarios across multiple test projects!
Setup:
- Add a project reference to the shared library:
<ItemGroup>
<ProjectReference Include="..\SharedAuthLibrary\SharedAuthLibrary.csproj" />
</ItemGroup>- Call scenarios from the referenced project:
Feature: Order Management
Scenario: Place Order as Authenticated User
Given I call scenario "Login with Valid Credentials" from feature "Shared Authentication"
When I navigate to the products page
And I proceed to checkout
Then I should see order confirmationHow it works:
- The plugin automatically discovers feature files from referenced projects
- No manual file copying or complex MSBuild configuration needed
- Scenarios are expanded at build time just like same-project calls
- Step definitions from referenced projects are available through dependency injection
Example: See examples/MSTestCrossProjectExample for a complete working example.
When a scenario call cannot be resolved, the plugin provides detailed diagnostic messages to help you identify and fix the issue. The original undefined scenario call line is removed from the generated output and replaced with an executable diagnostic step so the generated scenario fails instead of being skipped.
Example 1: Feature not found
Scenario: Test with Missing Feature
Given I call scenario "SomeScenario" from feature "NonExistent"
# ERROR: Could not find feature file for "NonExistent". Ensure the feature file exists in the project or referenced projects.
Given scenario call expansion failed: Could not find feature file for "NonExistent". Ensure the feature file exists in the project or referenced projects.Example 2: Scenario not found
Scenario: Test with Missing Scenario
Given I call scenario "NonExistent" from feature "Authentication"
# ERROR: Scenario "NonExistent" was not found in feature "Authentication". Check scenario name spelling and case.
Given scenario call expansion failed: Scenario "NonExistent" was not found in feature "Authentication". Check scenario name spelling and case.The plugin removes the original scenario call line and replaces it with a descriptive error comment plus a bound diagnostic step. This prevents the original line from appearing as an "undefined step" in your IDE while still failing the generated test.
Scenarios can contain calls to other scenarios, enabling complex composition:
BaseOperations.feature
Feature: Base Operations
Scenario: Setup Test Environment
Given the application is started
And the database is clean
Scenario: Complete Login Flow
Given I call scenario "Setup Test Environment" from feature "Base Operations"
When I call scenario "Login" from feature "Authentication"
Then I should see the dashboard- Feature names are case-insensitive
- Scenario names are case-insensitive
- File discovery is case-insensitive
The plugin supports all Gherkin languages that Reqnroll supports. Specify the language using the # language: directive at the top of your feature file.
Important: When using non-English languages, both the calling and called feature files must have the # language: directive at the top. The plugin will emit warnings if:
- A non-English calling feature references a feature file without a language directive
- Two feature files involved in a scenario call have different language directives
Dutch Example (AuthenticatieNL.feature)
# language: nl
Functionaliteit: Authenticatie
Scenario: Inloggen met geldige inloggegevens
Gegeven ik ben op de inlogpagina
Als ik gebruikersnaam "john.doe@example.com" invoer
En ik wachtwoord "SecurePassword123" invoer
Dan zou ik ingelogd moeten zijnUsing Dutch scenarios in your feature files:
# language: nl
Functionaliteit: Gebruikersbeheer
Scenario: Nieuw gebruikersaccount aanmaken
Gegeven I call scenario "Inloggen met geldige inloggegevens" from feature "Authenticatie"
Als ik naar het gebruikersbeheersectie navigeer
Dan zou ik de gebruikerslijst moeten zienGerman Example (AuthentifizierungDE.feature)
# language: de
Funktionalität: Authentifizierung
Szenario: Login mit gültigen Anmeldedaten
Angenommen ich bin auf der Login-Seite
Wenn ich Benutzername "john.doe@example.com" eingebe
Und ich Passwort "SecurePassword123" eingebe
Dann sollte ich eingeloggt seinUsing German scenarios in your feature files:
# language: de
Funktionalität: Benutzerverwaltung
Szenario: Neues Benutzerkonto erstellen
Angenommen I call scenario "Login mit gültigen Anmeldedaten" from feature "Authentifizierung"
Wenn ich zum Benutzerverwaltungsbereich navigiere
Dann sollte ich die Benutzerliste sehenSupported Languages: English (en), Dutch (nl), German (de), French (fr), Spanish (es), and many more. See Gherkin language reference for a complete list.
Mixed Language Support: You can call scenarios from feature files written in different languages. The plugin automatically detects the language of each feature file.
Background Support Translations:
The with background phrase is automatically translated for each supported language:
- English:
with background - Dutch:
met achtergrond - German:
mit Hintergrund - French:
avec contexte - Spanish:
con antecedentes
Example in German:
# language: de
Funktionalität: Benutzerverwaltung
Szenario: Benutzer mit Hintergrund erstellen
Angenommen ich rufe Szenario "Login mit gültigen Anmeldedaten" auf aus Funktionalität "Authentifizierung" mit Hintergrund
Wenn ich einen neuen Benutzer erstelle
Dann sollte der Benutzer erstellt werden- .NET Standard 2.0 or higher
- Reqnroll (compatible with SpecFlow migration)
- MSBuild or .NET CLI for build-time processing
Issue: Scenario not found
# Warning: Could not expand scenario call
Solution:
- Verify the feature name matches the
Feature:declaration exactly - Ensure the scenario name exists in the target feature file
- Check that the feature file is in a discoverable location
Issue: Infinite recursion Solution: The plugin now automatically detects and prevents circular references. If you see an error message like "Circular reference detected", check your scenario calls to ensure they don't create a loop.
Issue: Feature file not found Solution:
- Ensure feature files are included in the project build
- Verify the feature file path is in one of the searched directories
- Check file naming conventions (
.featureextension required)
- Check the generated test files to see expanded scenario content
- Enable verbose MSBuild logging to see plugin activity
- Verify feature file discovery paths match your project structure
Circular scenario call references are not detected✅ FIXED: Circular references are now automatically detected and preventedCalling scenarios within the same feature file is not supported✅ FIXED: Same-feature scenario calls are now fully supported- Scenario Outline templates cannot be called directly (use regular Scenario: instead)
- Nested scenario calls are not recursively expanded (scenario calls within called scenarios remain as-is)
- Parameters cannot be passed between called scenarios
We welcome contributions! Please see our Contributing Guidelines for details.
- Clone the repository
- Install .NET 8.0 SDK or higher
- Restore packages:
dotnet restore - Build:
dotnet build - Run tests:
dotnet test
# Run all tests
dotnet test
# Run tests with verbose output
dotnet test --verbosity normal
# Run specific test
dotnet test --filter "TestMethodName"- Initial release
- Basic scenario calling functionality
- Automatic feature file discovery
- Error handling for missing scenarios
- Support for all Gherkin step keywords
This project uses GitHub Actions for automated building, testing, and publishing to NuGet.org.
The pipeline automatically:
-
On every push to main/master and pull requests:
- Sets up .NET 8.0 environment
- Restores NuGet dependencies
- Builds the solution in Release configuration
- Runs all tests
- Creates NuGet packages
- Uploads packages as build artifacts
-
On every push to main/master (automatic releases):
- Automatically increments the patch version (e.g., 3.0.0 → 3.0.1)
- Updates version numbers in the project file
- Builds and tests with the new version
- Creates a GitHub release with the new tag
- Attaches the NuGet package to the release
-
On GitHub releases:
- Downloads the build artifacts
- Publishes the NuGet package to nuget.org
New in this version: Every commit to the main branch now automatically creates a new release!
The versioning follows the pattern described in the CHANGELOG.md:
- MAJOR.MINOR: Matches the Reqnroll version (e.g., 3.0 for Reqnroll 3.0.x)
- PATCH: Automatically incremented on each commit to main (3.0.0 → 3.0.1 → 3.0.2, etc.)
Automatic Process (recommended):
- Simply push changes to the main branch
- The CI/CD pipeline will automatically:
- Increment the patch version
- Create a GitHub release
- Publish to NuGet.org
Manual Process (for major/minor version changes):
- Update the version in
Reqnroll.ScenarioCall.Generator.csproj:<Version>4.0.0</Version> <AssemblyVersion>4.0.0</AssemblyVersion> <FileVersion>4.0.0</FileVersion>
- Commit and push to main
- The pipeline will use your specified version instead of auto-incrementing
To enable automatic publishing, the repository requires a NUGET_API_KEY secret containing a valid NuGet.org API key with push permissions.
This project is licensed under the BSD 3-Clause License - see the LICENSE file for details.
- 📫 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions
- 📚 Documentation: This README and inline code documentation
- Reqnroll - The .NET BDD framework this plugin extends
- SpecFlow - The original framework (Reqnroll is the successor)
Made with ❤️ for the BDD community