gherkin-linter
1.7.2
dotnet tool install --global gherkin-linter --version 1.7.2
dotnet new tool-manifest
dotnet tool install --local gherkin-linter --version 1.7.2
#tool dotnet:?package=gherkin-linter&version=1.7.2
nuke :add-package gherkin-linter --version 1.7.2
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
- CI/CD Integration
- Advanced Features
- Troubleshooting
- Contributing
- License
Quick Start
Install the GherkinLinter as a .NET tool:
dotnet tool install --global gherkin-linter
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
- Strict mode for CI/CD pipelines
- Quiet mode for reduced verbosity
- Multi-targeting for .NET 6.0, 7.0, and 8.0
Installation
Install the Gherkin Linter as a global .NET tool from NuGet:
dotnet tool install --global gherkin-linter
To update to the latest version:
dotnet tool update --global gherkin-linter
To uninstall:
dotnet tool uninstall --global gherkin-linter
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
# Use strict mode (returns non-zero exit code when violations are found)
gherkin-linter lint --strict
# Use quiet mode (display only essential information)
gherkin-linter lint --quiet
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 |
indentation |
Enforces consistent indentation | type , size , enforceConsistency , allowMixed , etc. |
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
indentation
This rule enforces consistent indentation in Gherkin files.
# ❌ Bad - Inconsistent indentation
Feature: Test Feature
Scenario: Bad indentation
Given I am not indented
When I have too much indentation
Then I have wrong indentation
# ✅ Good - Consistent indentation
Feature: Test Feature
Scenario: Good indentation
Given I am properly indented
When I have consistent spacing
Then I follow the indentation rules
## Custom Rules
You can create custom rules by implementing the `IRuleProvider` interface in a new class library project:
```csharp
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
GherkinLinter includes MSBuild targets that can be used to integrate with your build process. The targets are automatically included when you install the NuGet package.
<PropertyGroup>
<GherkinLinterEnabled>true</GherkinLinterEnabled>
<GherkinLinterSkipInCI>true</GherkinLinterSkipInCI>
<GherkinLinterPreserveTestAssemblies>true</GherkinLinterPreserveTestAssemblies>
</PropertyGroup>
For more details, see the MSBuild Integration section in the CI/CD Integration guide.
CI/CD Integration
GherkinLinter now includes features to better integrate with CI/CD environments and prevent interference with test discovery and execution:
- CI/CD Environment Detection - Automatically detects when running in common CI/CD systems
- Build Integration Toggle - Allows disabling linting during automated builds
- Test Assembly Preservation - Prevents linting in directories containing test assemblies
- MSBuild Integration - Conditional execution based on environment and configuration
# Skip linting in CI/CD environments
gherkin-linter lint --skip-in-ci
# Skip linting in directories containing test assemblies
gherkin-linter lint --preserve-test-assemblies
For detailed information, see the CI_CD_INTEGRATION.md guide.
Advanced Features
Strict Mode
The strict mode flag (--strict
) makes the linter return a non-zero exit code when rule violations are found. This is particularly useful in CI/CD pipelines where you want the build to fail if there are linting errors.
# Normal mode - returns exit code 0 even with violations (for development)
gherkin-linter lint
# Strict mode - returns exit code 1 when violations are found (for CI/CD)
gherkin-linter lint --strict
Quiet Mode
The quiet mode flag (--quiet
or -q
) reduces the verbosity of the linter output, showing only essential information such as file paths with errors, the errors themselves, and a summary count. This is particularly useful in CI/CD pipelines or when you want to focus only on the errors without additional logging.
# Normal mode - shows detailed information about the linting process
gherkin-linter lint
# Quiet mode - shows only essential information (file paths, errors, and summary)
gherkin-linter lint --quiet
For more details about quiet mode, see QUIET_MODE.md.
Multi-targeting
The linter supports multiple .NET versions (6.0, 7.0, and 8.0), allowing you to use it with your preferred .NET runtime. The tool automatically selects the appropriate version based on what's installed on your system.
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.
See RELEASE_NOTES_v1.7.2.md for detailed release notes