AgentSkillsCN

cucumber-gherkin

使用Cucumber和Gherkin语法的全面BDD测试。在编写特性文件(.feature)、步骤定义、钩子或实施行为驱动开发时使用此功能。涵盖Gherkin关键字(特性、场景、给定/当/然后、背景、场景大纲、规则)、Ruby/JavaScript/Java/Python的步骤定义模式、钩子(Before/After/BeforeAll/AfterAll)、标签、数据表、文档字符串和最佳实践。在cucumber、gherkin、BDD、特性文件、步骤定义、验收测试、可执行规范时触发。

SKILL.md
--- frontmatter
name: cucumber-gherkin
description: Comprehensive BDD testing with Cucumber and Gherkin syntax. Use when writing feature files (.feature), step definitions, hooks, or implementing Behaviour-Driven Development. Covers Gherkin keywords (Feature, Scenario, Given/When/Then, Background, Scenario Outline, Rule), step definition patterns for Ruby/JavaScript/Java/Python, hooks (Before/After/BeforeAll/AfterAll), tags, data tables, doc strings, and best practices. Triggers on cucumber, gherkin, BDD, feature files, step definitions, acceptance testing, executable specifications.

Cucumber & Gherkin Skill

BDD testing framework with plain-text executable specifications. Gherkin syntax with step definitions in Ruby, JavaScript, Java, or Python.

Core Concepts

Cucumber reads executable specifications in plain text and validates software behavior. Gherkin is the structured grammar making plain text machine-readable.

code
┌────────────┐                 ┌──────────────┐                 ┌───────────┐
│   Steps    │                 │     Step     │                 │           │
│ in Gherkin ├──matched with──>│ Definitions  ├───manipulates──>│  System   │
└────────────┘                 └──────────────┘                 └───────────┘

Gherkin Syntax Quick Reference

Primary Keywords

gherkin
Feature: Short description
  Optional multi-line description explaining the feature.
  
  Background:
    Given common setup steps for all scenarios
  
  Rule: Business rule grouping (Gherkin 6+)
    
    Scenario: Concrete example illustrating the rule
      Given an initial context (past tense, setup)
      When an action occurs (present tense, trigger)
      Then expected outcome (assertion)
      And additional step
      But negative assertion
    
    Scenario Outline: Parameterized scenario
      Given there are <start> items
      When I remove <remove> items
      Then I should have <remaining> items
      
      Examples:
        | start | remove | remaining |
        |    12 |      5 |         7 |
        |    20 |      5 |        15 |

Step Keywords

KeywordPurposeExample
GivenSetup/preconditionGiven I am logged in as "admin"
WhenAction/triggerWhen I click the submit button
ThenAssertion/outcomeThen I should see "Success"
AndContinue previous typeAnd I have 3 items in my cart
ButNegative continuationBut I should not see "Error"
*Bullet-style step* I have eggs

Data Structures

Data Tables - tabular data:

gherkin
Given the following users exist:
  | name   | email              | role  |
  | Alice  | alice@example.com  | admin |
  | Bob    | bob@example.com    | user  |

Doc Strings - multi-line text:

gherkin
Given a blog post with content:
  """markdown
  # My Post Title
  
  This is the content of my blog post.
  """

Tags

gherkin
@smoke @critical
Feature: User authentication

  @wip
  Scenario: Login with valid credentials
    ...
  
  @slow @database
  Scenario: Bulk user import
    ...

Tag expressions: @smoke and not @slow, @gui or @api, (@smoke or @critical) and not @wip

Step Definitions

Match Gherkin steps to code. Use Cucumber Expressions (preferred) or Regular Expressions.

Ruby

ruby
Given('I have {int} cucumbers in my belly') do |count|
  @belly = Belly.new
  @belly.eat(count)
end

When('I wait {int} hour(s)') do |hours|
  @belly.wait(hours)
end

Then('my belly should growl') do
  expect(@belly.growling?).to be true
end

# With data table
Given('the following users exist:') do |table|
  table.hashes.each do |row|
    User.create!(row)
  end
end

JavaScript

javascript
const { Given, When, Then } = require('@cucumber/cucumber');

Given('I have {int} cucumbers in my belly', function(count) {
  this.belly = new Belly();
  this.belly.eat(count);
});

When('I wait {int} hour(s)', async function(hours) {
  await this.belly.wait(hours);
});

Then('my belly should growl', function() {
  expect(this.belly.isGrowling()).toBe(true);
});

// With data table
Given('the following users exist:', async function(dataTable) {
  for (const row of dataTable.hashes()) {
    await User.create(row);
  }
});

Java

java
public class StepDefinitions {
    @Given("I have {int} cucumbers in my belly")
    public void iHaveCucumbersInMyBelly(int count) {
        belly = new Belly();
        belly.eat(count);
    }
    
    @When("I wait {int} hour(s)")
    public void iWaitHours(int hours) {
        belly.wait(hours);
    }
    
    @Then("my belly should growl")
    public void myBellyShouldGrowl() {
        assertTrue(belly.isGrowling());
    }
}

Cucumber Expressions

Built-in parameter types: {int}, {float}, {word}, {string}, {} (anonymous)

Optional text: cucumber(s) matches "cucumber" or "cucumbers" Alternative text: color/colour matches "color" or "colour"

Hooks

Scenario Hooks

ruby
# Ruby
Before do |scenario|
  # runs before each scenario
end

After do |scenario|
  # runs after each scenario
  screenshot if scenario.failed?
end
javascript
// JavaScript
const { Before, After } = require('@cucumber/cucumber');

Before(async function(scenario) {
  // runs before each scenario
});

After(async function(scenario) {
  // runs after each scenario
  if (scenario.result.status === 'FAILED') {
    await this.screenshot();
  }
});

Conditional Hooks (with tags)

ruby
Before('@database') do
  DatabaseCleaner.start
end

After('@database') do
  DatabaseCleaner.clean
end
javascript
Before({ tags: '@browser and not @headless' }, async function() {
  this.browser = await launchBrowser();
});

Global Hooks

ruby
BeforeAll do
  # once before any scenario
end

AfterAll do
  # once after all scenarios
end

Best Practices

Declarative over Imperative

Good (declarative):

gherkin
When "Bob" logs in
Then he sees his dashboard

Avoid (imperative):

gherkin
When I visit "/login"
And I enter "bob" in "username"
And I enter "secret" in "password"
And I click "Login"
Then I should see "Dashboard"

Focus on Behavior, Not Implementation

  • Describe what the system does, not how
  • Use domain language stakeholders understand
  • Keep scenarios short (3-5 steps recommended)
  • One behavior per scenario

Background Usage

  • Keep backgrounds short (≤4 lines)
  • Use only for essential shared context
  • Move implementation details to step definitions

Running Cucumber

bash
# Ruby
bundle exec cucumber
cucumber --tags "@smoke and not @wip"
cucumber features/login.feature:10  # specific line

# JavaScript
npx cucumber-js
npx cucumber-js --tags "@smoke"

# Java (with Maven)
mvn test -Dcucumber.filter.tags="@smoke"

Additional References

For comprehensive details, see reference files:

  • references/gherkin-syntax.md - Complete Gherkin language reference
  • references/step-definitions.md - Step definition patterns by language
  • references/hooks-config.md - Hooks, configuration, and runners
  • references/best-practices.md - Anti-patterns and advanced patterns