gherkin-linter
1.1.0
See the version list below for details.
dotnet tool install --global gherkin-linter --version 1.1.0
dotnet new tool-manifest
dotnet tool install --local gherkin-linter --version 1.1.0
#tool dotnet:?package=gherkin-linter&version=1.1.0
nuke :add-package gherkin-linter --version 1.1.0
Gherkin Linter for C# Projects
A pure C# implementation of a Gherkin linter for SpecFlow and other BDD frameworks, designed to integrate seamlessly with C# projects.
Table of Contents
- Quick Start
- Features
- Installation
- Usage
- Configuration
- Built-in Rules
- Custom Rules
- Integration with MSBuild
- Updating Dependencies in Other Projects
- Troubleshooting
- Contributing
- License
Quick Start
Install the GherkinLinter as a .NET tool:
dotnet tool install --global GherkinLinter.Cli
Lint your feature files:
gherkin-linter lint
Set up a Git pre-commit hook to automatically lint staged feature files:
gherkin-linter install
Features
- Lint Gherkin feature files to ensure quality and consistency
- Built-in rules for common Gherkin issues
- Custom rule support
- Git pre-commit hook integration
- Configurable via JSON
- No Node.js or JavaScript dependencies
Installation
Option 1: Add to Your C# Project
- Clone this repository or download the source code
- Add the GherkinLinter solution to your project:
git clone https://github.com/yourusername/GherkinLinter.git
- Reference the project in your solution
Option 2: Install as .NET Tool
Install from NuGet:
dotnet tool install --global GherkinLinter.Cli
Usage
Command Line Interface
# Lint all feature files
gherkin-linter lint
# Lint only staged feature files
gherkin-linter lint --staged
# Lint a specific feature file
gherkin-linter lint --file path/to/feature.feature
# Use a specific configuration file
gherkin-linter lint --config path/to/config.json
For project reference usage:
dotnet run --project path/to/GherkinLinter.Cli/GherkinLinter.Cli.csproj lint
Git Pre-commit Hook Setup
# Install the pre-commit hook
gherkin-linter install
This will:
- Set up a Git pre-commit hook
- Create a default configuration file
Configuration
The linter uses a JSON configuration file named .gherkin-linter.json
in your project root:
{
"include": [
"Features/**/*.feature",
"**/*.feature"
],
"exclude": [
"bin/**/*.feature",
"obj/**/*.feature"
],
"rules": {
"scenario-names": {
"enabled": true
},
"no-empty-steps": {
"enabled": true
},
"no-duplicate-scenario-names": {
"enabled": true
},
"max-step-length": {
"enabled": true,
"config": {
"length": 100
}
},
"weak-language": {
"enabled": true
}
},
"custom_rules": []
}
Built-in Rules
Rule | Description | Configuration |
---|---|---|
scenario-names |
Ensures all scenarios have names | None |
no-empty-steps |
Ensures all steps have descriptions | None |
no-duplicate-scenario-names |
Checks for duplicated scenario names | None |
max-step-length |
Limits step length | length : Maximum characters (default: 100) |
weak-language |
Checks for weak language patterns in steps | Customizable phrase mappings for Given/When and Then steps |
Rule Examples
scenario-names
This rule ensures that all scenarios have a name. Unnamed scenarios make it difficult to understand the purpose of the test.
# ❌ Bad - Unnamed scenario
Scenario:
Given I am on the homepage
When I click the login button
Then I should see the login form
# ✅ Good - Named scenario
Scenario: User can navigate to login form
Given I am on the homepage
When I click the login button
Then I should see the login form
no-empty-steps
This rule checks for steps that have no description.
# ❌ Bad - Empty step
Scenario: User login
Given I am on the login page
When
Then I should be logged in
# ✅ Good - All steps have descriptions
Scenario: User login
Given I am on the login page
When I enter my credentials and click login
Then I should be logged in
no-duplicate-scenario-names
This rule ensures that all scenarios have unique names within a feature file.
# ❌ Bad - Duplicate scenario names
Scenario: User login
Given I am on the login page
When I enter valid credentials
Then I should be logged in
Scenario: User login
Given I am on the login page
When I enter invalid credentials
Then I should see an error message
# ✅ Good - Unique scenario names
Scenario: User login with valid credentials
Given I am on the login page
When I enter valid credentials
Then I should be logged in
Scenario: User login with invalid credentials
Given I am on the login page
When I enter invalid credentials
Then I should see an error message
max-step-length
This rule limits the length of step descriptions to improve readability.
# ❌ Bad - Step is too long
Scenario: User registration
Given I am on the registration page
When I enter my first name, last name, email address, phone number, street address, city, state, zip code, country, preferred contact method, and marketing preferences
Then I should be registered
# ✅ Good - Steps are concise
Scenario: User registration
Given I am on the registration page
When I fill out the registration form with valid data
And I submit the form
Then I should be registered
weak-language
This rule identifies steps that use weak or ambiguous language.
# ❌ Bad - Uses weak language
Scenario: User login
Given I am on the login page
When I enter my credentials
Then I should be able to see my dashboard
# ✅ Good - Uses specific language
Scenario: User login
Given I am on the login page
When I enter valid credentials and click login
Then the dashboard is displayed with my account information
Custom Rules
You can create custom rules by implementing the IRuleProvider
interface in a new class library project:
using System.Collections.Generic;
using GherkinLinter.Core;
namespace YourNamespace
{
public class YourCustomRuleProvider : IRuleProvider
{
public IEnumerable<RuleViolation> ApplyRule(Feature feature, Dictionary<string, object> config)
{
var violations = new List<RuleViolation>();
// Your rule logic here
// Example: Check if feature name follows a pattern
if (!feature.Name.StartsWith("JIRA-"))
{
violations.Add(new RuleViolation
{
Message = "Feature name must start with JIRA-",
Line = feature.Line
});
}
return violations;
}
}
}
Then reference your class library and add the rule to your configuration:
{
"rules": {
"your-custom-rule": {
"enabled": true,
"config": {
"yourSetting": "value"
}
}
},
"custom_rules": [
{
"path": "path/to/your/assembly.dll",
"config": {
"additionalSetting": "value"
}
}
]
}
Integration with MSBuild
To run the linter as part of your build process, add this to your .csproj
file:
<Target Name="LintGherkin" BeforeTargets="BeforeBuild">
<Exec Command="gherkin-linter lint" />
</Target>
Updating Dependencies in Other Projects
If you're using GherkinLinter in other projects (like Tsp.Test), you can use the included PowerShell script to update the dependencies:
# Run from the GherkinLinter project root
.\update-tsp-test.ps1
This script will:
- Automatically increment the patch version number (e.g., 1.0.0 → 1.0.1)
- Build the GherkinLinter project in Release mode
- Copy all necessary files to the Tsp.Test project
- Verify the update by checking the version
The script automatically handles version management by incrementing the patch version with each update. If you need to make a major or minor version change (e.g., for breaking changes or new features), you'll need to manually update the version number in src/GherkinLinter.Cli/GherkinLinter.Cli.csproj
.
You may need to modify the script if your project paths are different.
Troubleshooting
Common Issues
- Configuration File Not Found: Ensure your
.gherkin-linter.json
file is in the root of your project. - Rules Not Working: Check that the rules are enabled in your configuration file.
- Git Hook Not Working: Verify that the pre-commit hook is executable and properly installed.
Debugging
For more detailed output, use the verbose flag:
gherkin-linter lint --verbose
Contributing
Contributions are welcome! Here's how you can contribute:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Please ensure your code follows the existing style and includes appropriate tests.
License
MIT
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.