Testland
Browse all skills & agents

gherkin-from-stories

Converts requirements in any input shape into Gherkin scenarios - a user story ("As a … I want … so that …"), a signed-off acceptance-criteria list (ATDD: @AC-N-tagged scenarios, NotImplementedError step stubs, AC-to-test traceability table), existing manual test steps (declarative rewrite that strips UI mechanics), or a raw spec / PRD section (acceptance-criteria extraction with Gherkin or plain-list output). Maps criteria to Scenario blocks, detects Scenario Outline opportunities, factors shared Background, reuses the curated step library, and flags implicit preconditions instead of fabricating them. Emits Gherkin (plus stubs in ATDD mode): runner detection and full step wiring belong to bdd-scenario-author. Use whenever requirements text of any shape needs to become a .feature file.

Install with skills.sh (any agent)

npx skills add testland/qa --skill gherkin-from-stories
View source

gherkin-from-stories

Overview

The shift-left flow:

Spec / User story → Acceptance Criteria → Gherkin Feature → Step definitions → Tests

This skill is the authoring umbrella for the left half of that flow: it turns requirements text into a .feature file. Four input shapes route to the same core transform:

Input you haveSection to useExtra output
A user story with the As-a / I-want / So-that triple"From a user story"-
A signed-off, numbered acceptance-criteria list"From an acceptance-criteria list (ATDD)"@AC-N tags, step stubs, traceability table
Already-written manual test steps (TestRail / Qase / Xray export, prose script)"From manual test steps"side-by-side rewrite table
A raw spec / PRD section with no AC structure yet"Extracting acceptance criteria from a raw spec"Gherkin or plain numbered AC list

Whatever the input, the same core discipline applies: one Scenario per behavior, Scenario Outline when only data varies, shared Background, step library reuse, and flag-and-ask on implicit preconditions.

When to use

  • A PM hands over a story, spec, or AC list and the team's first test artifact is the .feature file.
  • The team practices ATDD and gates stories on green acceptance tests.
  • A team is migrating manual test scripts (or a whole TestRail / Qase library) to BDD.
  • A migration from non-BDD to BDD wants to convert existing requirements into Gherkin in bulk.

Not this skill: reviewing existing Gherkin for style (use gherkin-style-reviewer); wiring step definitions to a runner end to end (use bdd-scenario-author, which invokes this skill first); non-functional requirements - perf / a11y / security thresholds have a different shape (thresholds, not Given/When/Then) - use non-functional-requirement-extractor in the qa-shift-left plugin.

From a user story

Step 1 - Extract the user-story triple

# Story: Apply promo code at checkout

**As a** logged-in customer
**I want** to apply a promotional code at checkout
**So that** I receive the advertised discount on my order

The triple maps to the Feature header:

Feature: Apply promo code at checkout

  As a logged-in customer
  I want to apply a promotional code at checkout
  So that I receive the advertised discount on my order

If the story doesn't have the triple, flag and ask - a story without explicit value is a signal the team should clarify before testing.

Step 2 - Map acceptance criteria to Scenarios

The story body usually has an AC list; each AC becomes a Scenario:

  Background:
    Given I am a logged-in customer
    And my cart contains 1 item at $24.99

  Scenario: Apply valid promo
    Given promo code "WELCOME10" is active
    When I enter "WELCOME10" in the promo input
    And I click "Apply"
    Then the subtotal updates to $22.49
    And a confirmation toast appears: "Code applied"

  Scenario: Apply expired promo
    Given promo code "EXPIRED50" is inactive
    When I enter "EXPIRED50" in the promo input
    And I click "Apply"
    Then an error appears: "This code has expired"

Step 3 - Identify Scenario Outline opportunities

Multiple ACs that vary only in input data become a Scenario Outline - use one whenever the underlying logic is identical and only the data varies:

  Scenario Outline: Promo validation rejects bad input
    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        |
      | (empty)      | Please enter a code   |
      | WELCOME10*2  | Already applied       |

From an acceptance-criteria list (ATDD)

When the input is a signed-off, numbered AC list and the team gates implementation on green acceptance tests (per ISTQB, ATDD is "a collaboration-based test-first approach that defines acceptance tests in the stakeholders' domain language"):

  1. One Scenario per AC, tagged @AC-X.Y - the tag is the load-bearing traceability that maps failures back to the criterion.
  2. Tests are written before implementation - the initial run fails on every scenario, and the failing tests are the work backlog.
  3. Scaffold step stubs whose bodies raise NotImplementedError (or PendingException) so nothing passes silently.
  4. Emit the AC-to-test traceability table - a 1:1 mapping of AC → test → status that answers "did we test what the customer asked for?"
  5. Run via the team's incumbent BDD runner - never force a runner switch alongside test-first adoption.

The full worked feature, stub examples, traceability artifact, per-runner tag-filter commands, and ATDD-specific anti-patterns: references/atdd-traceability.md.

From manual test steps

When the input is an already-written manual step (table row, prose bullet, TestRail / Qase / Xray exported step), the job is a declarative rewrite, not a translation: strip UI mechanics ("clicks the button", "types in the field"), elevate user intent ("signs in", "adds the product"), and align vocabulary with the existing step library.

  1. Classify each step: UI mechanic / state assertion / business action / setup / observation. Mechanics and assertions get rewritten; business actions pass through; setup becomes Given; observations drop into step-definition detail.
  2. Apply the rewrite rules R1-R5: remove UI mechanics, collapse multi-step UI sequences into one business action, replace UI properties with observable outcomes, choose the right keyword, preserve existing vocabulary.
  3. Emit a side-by-side table (manual step → Gherkin step → keyword → justification) so a reviewer can confirm semantic equivalence.
  4. Validate: at most one When per scenario; lint; specificity preserved (cart count "1" stays "one item", never "non-empty").

The classification table, the full R1-R5 rule catalog with examples, and migration-specific anti-patterns: references/manual-step-rules.md.

Extracting acceptance criteria from a raw spec

When the input is a PRD section or feature spec with no AC structure yet, extract the criteria first, then feed them through the sections above. Emits two interchangeable shapes: Gherkin (for Cucumber / Behave / Reqnroll / pytest-bdd projects) or a plain numbered list (AC-1, AC-2, … - consumable by the ATDD section and usable as commit-message references, e.g. feat: AC-3 - show toast on save).

  1. Tag each sentence as Given (steady state / actor context), When (action verbs: "clicks", "submits", "navigates"), or Then (asserted outcomes), per the Gherkin reference.
  2. Choose Scenario vs Scenario Outline - Outline + Examples: for boundary checks, role variants, status-code matrices.
  3. Factor out Background for truly shared state (auth, seed data, navigation) - only one Background per Feature; don't over-extract scenario-specific setup.
  4. Validate observability of every Then. Reject "Then the user feels confident" / "Then the system is secure"; replace with concrete targets: a visible data-testid, a response status, a header present.
  5. Flag implicit Givens (below) rather than fabricating.

Three worked examples (simple story, PRD with implicit preconditions, Scenario Outline opportunity): references/spec-extraction-examples.md.

Shared discipline (all input shapes)

Use existing steps from the library

Per bdd-step-library-curator, the team has a curated step library. Use existing steps where possible:

# Use existing step:
Given I am a logged-in customer

# vs (avoid):
Given I have authenticated to the system   # NEW STEP - duplicates "I am a logged-in customer"

Before authoring a new step, search the library README.

Flag implicit Givens

Requirements often imply preconditions. Flag instead of guess:

## ⚠ Implicit Given flags (3)

1. Where does the user enter the promo? `/checkout`? `/cart`?
2. What's the cart state? Empty? Multi-item?
3. Authentication required? Guest checkout supported?

The Gherkin Feature can't be authored without these answers.

Flag-and-ask is the load-bearing pattern: silently picking one reading produces a test suite that misses the paths the author never confirmed.

Validate Gherkin style

  • Declarative steps ("I apply a promo") not imperative ("I click the button with id #apply-promo-btn").
  • Every Then has an observable outcome.
  • No technical leakage (DB names, internal API endpoints, CSS selectors).

Output

## Gherkin scenarios for `<source>`

**Source:** `LIN-1234` (story) | AC list | manual script | PRD section
**Implicit-precondition flags:** N
**Scenarios produced:** M
**Step library reuse:** K of M scenarios use existing steps only.

### Generated Feature
### Implicit-precondition flags
### New steps required

| Step                                          | Why new |
|-----------------------------------------------|---------|
| `Given promo code {code} is active`           | New domain (admin promo state) |

### Recommended next step

After the PM clarifies flagged Givens, author the new step definitions per
`bdd-step-library-curator` conventions and pair with the team's runner
(`cucumber-testing` / `behave-testing` / `reqnroll-testing`), or hand the
whole flow to `bdd-scenario-author`.

Anti-patterns

Anti-patternWhy it failsFix
Fabricating implicit GivensTests pass for the wrong reason; the author never confirmedFlag-and-ask
One Scenario per AC even when they should be an OutlineTest code duplicationDetect outline opportunities
Not consulting the step libraryStep proliferation; library bloatsSearch library first
Imperative steps ("click button #foo")Couples to UI; defeats BDD's valueDeclarative ("I apply a promo")
Skipping the As-a / I-want / So-that headerLoses the value framingTriple at the Feature top
Then with a verb but no observable target ("Then save")Not testableEmit data-testid / response status / DOM state
Copy-pasted Givens across scenariosBackground extraction missed; brittle suiteOne Background block for shared state

Limitations

  • Input quality drives output quality. Vague stories and specs produce vague Gherkin (or many flags).
  • Step library dependency. Without one, every step is "new" and the proliferation problem manifests.
  • Doesn't run the tests. This skill emits Gherkin (plus stubs in ATDD mode); pair with the runner skills or bdd-scenario-author for the runnable artifact.
  • ATDD mode requires the team to write ACs first and doesn't replace lower-layer tests - unit / integration coverage is still needed for non-AC logic.

References

  • references/atdd-traceability.md - the full ATDD workflow: tagged scenarios, red-first, stubs, traceability.
  • references/manual-step-rules.md - the manual-step classification + R1-R5 declarative-rewrite rules.
  • references/spec-extraction-examples.md - worked spec-extraction examples.
  • Cucumber Gherkin reference (keywords, Outline + Examples, Background rules): https://cucumber.io/docs/gherkin/reference
  • Cucumber Better Gherkin (declarative vs imperative): https://cucumber.io/docs/bdd/better-gherkin/
  • ISTQB Glossary V4.7.1 - acceptance criteria (https://glossary.istqb.org/en_US/term/acceptance-criteria) and ATDD (https://glossary.istqb.org/en_US/term/acceptance-test-driven-development).
  • bdd-step-library-curator - the step library this skill draws from.
  • bdd-scenario-author - downstream agent that wires the Feature to a detected runner.

ATDD from an acceptance-criteria list - tags, stubs, traceability

View source (opens in new window)

ATDD from an acceptance-criteria list - tags, stubs, traceability

Deep reference for gherkin-from-stories ("from an acceptance-criteria list" input shape). Consult when the team practices ATDD and needs the full tagged-scenario, red-first, traceability workflow.

Per ISTQB Glossary V4.7.1, ATDD (Acceptance Test-Driven Development) is "a collaboration-based test-first approach that defines acceptance tests in the stakeholders' domain language" (https://glossary.istqb.org/en_US/term/acceptance-test-driven-development). The flow: Story → AC → Acceptance test → Implementation → Pass. The acceptance test is written first; the implementation follows; success = test passes.

One tagged test per AC

Input AC list (each AC has an ID - preserved end-to-end so test failures map back):

## Acceptance criteria

- AC-1.1: Valid promo "WELCOME10" reduces subtotal by 10%.
- AC-1.2: Expired promo shows the message "This code has expired."
- AC-1.3: Empty promo input shows "Please enter a code."
- AC-1.4: Already-applied promo shows "Already applied" without re-applying.
- AC-1.5: Promo applies before tax (per current pricing logic).
# Features/promo-application.feature
Feature: Apply promo code at checkout

  Background:
    Given a logged-in customer
    And the cart contains 1 of "BOOK-001" at $24.99

  @AC-1.1
  Scenario: Valid promo reduces subtotal
    Given promo code "WELCOME10" is active
    When I enter "WELCOME10" in the promo input
    And I click "Apply"
    Then the subtotal updates to $22.49

  @AC-1.2
  Scenario: Expired promo shows error
    Given promo code "EXPIRED50" is inactive
    When I enter "EXPIRED50" in the promo input
    And I click "Apply"
    Then an error appears: "This code has expired"

  @AC-1.3
  Scenario: Empty promo input
    When I enter "" in the promo input
    And I click "Apply"
    Then an error appears: "Please enter a code"

  @AC-1.4
  Scenario: Already-applied promo
    Given promo code "WELCOME10" is active
    And I have already applied "WELCOME10"
    When I enter "WELCOME10" in the promo input
    And I click "Apply"
    Then an error appears: "Already applied"
    And the subtotal remains $22.49

  @AC-1.5
  Scenario: Promo applies before tax
    Given the tax rate for this region is 10%
    And promo code "WELCOME10" is active
    When I enter "WELCOME10" in the promo input
    And I click "Apply"
    Then the subtotal updates to $22.49
    And the tax updates to $2.249 (10% of $22.49)
    And the total is $24.74

The @AC-X.Y tag is the load-bearing traceability: failing tests report which AC failed.

Initial state - all tests fail

Per ATDD, tests are written before implementation. Initial run:

Scenario: Valid promo reduces subtotal
  Given promo code "WELCOME10" is active           # PASS (admin seeding works)
  When I enter "WELCOME10" in the promo input      # PASS (input field exists)
  And I click "Apply"                              # PASS (button exists)
  Then the subtotal updates to $22.49              # FAIL - promo logic not implemented

5 of 5 scenarios FAILED (as expected - implementation pending).

The failing tests are the work backlog. Implementation drives them green one by one; the story is "done" only when all AC tests pass - per the team's DoD (definition-of-done in the qa-process plugin).

Scaffold new step definitions

Detect undefined steps and emit stub definitions whose bodies raise:

# features/steps/promo_steps.py

@given('promo code "{code}" is active')
def step_promo_active(context, code):
    raise NotImplementedError(f"Implement: seed promo {code} as active")

@when('I enter "{code}" in the promo input')
def step_enter_promo(context, code):
    raise NotImplementedError(f"Implement: type {code} in promo input")

@then('an error appears: "{message}"')
def step_error_appears(context, message):
    raise NotImplementedError(f"Implement: assert error message {message}")

@then('the subtotal updates to ${expected:f}')
def step_subtotal(context, expected):
    raise NotImplementedError(f"Implement: assert subtotal == {expected}")

The NotImplementedError body makes the test failure helpful - the engineer knows exactly what to implement. Auto-generated step bodies that pass silently are the cardinal ATDD sin: tests appear green while production code never runs.

Traceability artifact

## AC-to-test mapping - `<story>` (auto-generated)

| AC ID  | Test                                             | Status  | Last run |
|--------|--------------------------------------------------|---------|----------|
| AC-1.1 | `promo-application.feature:8` (Valid promo)      | pass    | 2026-05-05 |
| AC-1.2 | `promo-application.feature:14` (Expired)         | pass    | 2026-05-05 |
| AC-1.3 | `promo-application.feature:20` (Empty)           | pass    | 2026-05-05 |
| AC-1.4 | `promo-application.feature:25` (Already applied) | pass    | 2026-05-05 |
| AC-1.5 | `promo-application.feature:32` (Tax interaction) | pass    | 2026-05-05 |

**Coverage:** 5/5 AC covered by tests. Story is testable per ATDD.

This artifact answers "Did we test what the customer asked for?" - a 1:1 mapping of AC → test → status answers it definitively, and closes the compliance / audit gap.

Run via the team's framework

Default: match the team's existing BDD runner - ATDD lives or dies by adoption, and forcing a runner switch alongside test-first authoring stalls both. Use the incumbent runner (Cucumber-JVM, Behave, or Reqnroll). Pick a new runner only when no incumbent exists; then default to the production stack's primary language (JVM → Cucumber-JVM, Python → Behave, .NET → Reqnroll).

# Cucumber-JVM
mvn test -Dcucumber.filter.tags='@AC-1.1 or @AC-1.2 or @AC-1.3 or @AC-1.4 or @AC-1.5'

# Behave
behave --tags=@AC-1.1 --tags=@AC-1.2 --tags=@AC-1.3 --tags=@AC-1.4 --tags=@AC-1.5

# Reqnroll
dotnet test --filter "Category=AC-1.1|Category=AC-1.2|..."

ATDD-specific anti-patterns

Anti-patternWhy it failsFix
Tests written after implementationDefeats ATDD; tests verify what was built, not what was askedTest-first; tests precede implementation
Tests without @AC-X.Y tagNo traceability; story acceptance unverifiableTag every Scenario
One mega-scenario covering all ACsFailure mid-scenario doesn't pinpoint which AC failedOne Scenario per AC
Auto-generated step bodies that pass silentlyTests appear green; production code never runsNotImplementedError stubs
Skipping the AC-to-test artifactCompliance / audit gapGenerate the mapping each release
AC tests in the same suite as unit testsMixed feedback; harder to interpretSeparate features/acceptance/ suite

Manual test steps to declarative Gherkin - classification and rewrite rules

View source (opens in new window)

Manual test steps to declarative Gherkin - classification and rewrite rules

Deep reference for gherkin-from-stories ("from manual test steps" input shape). Consult when migrating manual scripts (TestRail / Qase / Xray exports) to BDD or handing a manual script to an automation engineer.

A manual test script and a Gherkin scenario describe the same behavior at different abstraction levels. Manual scripts are imperative ("click the Add to Cart button, then verify the cart count is 1"); Gherkin steps should be declarative ("the customer adds a product to their cart, then their cart shows one item"). The conversion goes wrong in a predictable way: one-for-one translation of UI mechanics produces brittle, implementation-coupled scenarios that Cucumber's own guidance warns against (https://cucumber.io/docs/bdd/better-gherkin/).

Step 1 - Classify each manual step

TagPatternExample
UI mechanicVerbs like "click", "tap", "type", "press", "select from dropdown", "navigate to", "scroll" combined with a UI element."Click the Add to Cart button"
State assertion"Verify", "check", "confirm", "ensure" combined with an observable property."Verify the cart count is 1"
Business actionA domain-level verb already (signs in, places order, cancels subscription)."User signs in with valid credentials"
Setup / precondition"Given that…", "Assuming…", "Pre-requisite:"."Given the user is logged in"
Observation / data inspection"Note the order ID for later use", "record the timestamp"."Capture the response time"

UI mechanics and state assertions are the two types to rewrite. Business actions are already declarative - pass them through. Setup converts to Given. Observations are typically dropped from Gherkin and lifted into step-definition implementation details.

Step 2 - Declarative-rewrite rules

The test for whether a step is too imperative: would the wording need to change if the implementation changed (e.g., the UI moved from a button to a voice command)? If yes, rewrite (https://cucumber.io/docs/bdd/better-gherkin/).

Rule R1 - Remove UI mechanics

ImperativeDeclarative
"Click the Add to Cart button""the customer adds a product to their cart"
"Type user@example.com in the email field""the customer signs in as user@example.com"
"Press the Submit button""the customer submits the form"
"Select USA from the country dropdown""the customer chooses USA as their country"
"Scroll to the bottom of the page"(drop - implementation detail; Gherkin should not require it)

Rule R2 - Collapse multi-step UI sequences into one business action

A manual script that says "type email; type password; click Submit" becomes one Gherkin step: When the customer signs in with valid credentials. The business action is "signing in", not "clicking, typing, clicking". The mechanics live in the step definition.

Rule R3 - Replace UI properties with observable outcomes

ImperativeDeclarative
"Verify the cart count is 1""their cart contains one item"
"Confirm the Submit button is disabled""the form cannot be submitted"
"Check that the URL is /dashboard""the customer is on the dashboard"
"Verify that the green checkmark appears""the operation is confirmed"

Rule R4 - Choose the right keyword

Manual step intentGherkin keyword
Setup state that exists before the user acts in this scenarioGiven
The user (or system) takes an action under testWhen
An observable consequence is assertedThen
Add detail to a previous step (same keyword type)And
Negate / contrast a previous stepBut

And and But inherit the type of the previous keyword - they are not interchangeable with Given/When/Then (https://cucumber.io/docs/gherkin/reference/).

Rule R5 - Preserve the project's existing vocabulary

Before emitting the rewrite, scan the project's existing Gherkin for the same business action. If "the customer signs in" is already used, do not introduce "the user logs in" - vocabulary drift fragments the step library and forces step-definition duplication. bdd-step-library-curator audits and consolidates that vocabulary.

Step 3 - Emit a side-by-side rewrite table

Output is a markdown table so a reviewer can confirm semantic equivalence:

Manual step (input)Gherkin step (output)KeywordJustification
Click the Add to Cart button on the SKU-001 product pagethe customer adds SKU-001 to their cartWhenR1 strips UI mechanic; business action elevated
Verify the cart count is 1their cart contains one itemThenR3 swaps UI property for observable outcome
Type email; type password; click Submitthe customer signs in as user@example.comWhenR2 collapses three UI mechanics to one business action
Pre-requisite: User is logged inthe customer is signed inGivenR4 chooses Given for setup
Note the order ID(dropped - implementation detail)-Out-of-scope for Gherkin per R1

The surviving rows assemble into a Scenario:

Scenario: Customer adds an in-stock product to their cart
  Given the customer is signed in
  When the customer adds SKU-001 to their cart
  Then their cart contains one item

Step 4 - Validate against project conventions

  1. Check the project step library for matching existing steps; flag new steps for bdd-step-library-curator review.
  2. Confirm the scenario has at most one When. Multiple Whens indicate two scenarios were collapsed; split them.
  3. Lint with the project's Gherkin linter (gherkin-lint, picklesdoc, or the IDE's built-in).
  4. Diff the rewrite against the manual step's expected outcome - semantic equivalence is the bar. If the manual step asserts "cart count is 1" but the rewrite asserts "cart is non-empty", that is a regression in specificity, not a successful abstraction.

Migration-specific anti-patterns

Anti-patternWhy it failsFix
One-for-one translation that keeps "the customer clicks the button"Brittle to UI changes; Cucumber explicitly warns against itApply R1 strictly
Multiple Whens in one scenario after collapsingThe scenario contains two business actionsSplit into two scenarios
Inventing new vocabulary when matching steps existVocabulary drift; duplicate step definitionsCross-reference the existing library (R5)
Dropping all Then assertions because they "look like UI checks"The scenario becomes unverifiableR3 rewrites assertions; doesn't drop them
Translating every UI mechanic, including business-relevant ones"Selects USA as country" may be load-bearing; "scrolls to footer" is notPreserve domain-meaningful selections
Gherkin that needs a comment to explainThe rewrite is wrongMake the scenario self-explanatory

Migration-specific limitations

  • Vocabulary alignment is the bottleneck, not translation. For large projects, run bdd-step-library-curator first to canonicalize vocabulary.
  • Some manual steps are inherently UI-mechanical. A11y tests asserting "the Skip to main link is the first focusable element" cannot be rewritten into business language without losing the spec - pass through with R1 disabled and tag @a11y for the team to decide.
  • Numerical specificity is preserved, not abstracted. "Cart count is 1" stays "cart contains one item" - not "cart is non-empty".
  • Output is a draft. A human reviews the side-by-side before merging.

Sources

  • Cucumber - Better Gherkin (declarative vs imperative): https://cucumber.io/docs/bdd/better-gherkin/
  • Cucumber - Gherkin reference (keyword semantics): https://cucumber.io/docs/gherkin/reference/
  • ISTQB glossary - test procedure (the imperative form abstracted away from): https://glossary.istqb.org/en_US/term/test-procedure

Extracting acceptance criteria from raw specs - worked examples

View source (opens in new window)

Extracting acceptance criteria from raw specs - worked examples

Deep reference for gherkin-from-stories ("from a raw spec / PRD" input shape). Three end-to-end examples of natural-language spec text turned into acceptance criteria; the extraction method lives in the SKILL.md section.

Example 1: simple story -> 2 scenarios

Input (Linear story):

"Title: Email update on profile page

As a logged-in user, I want to update my email address from /profile/settings. After update, the email field shows the new value and I see a confirmation toast."

Output:

Feature: Email update on profile page

  As a logged-in user
  I want to update my email address from /profile/settings
  So that my account contact information stays current

  Background:
    Given a logged-in user with email confirmed
    And the user is on the /profile/settings page

  Scenario: Update email to a new valid address
    When the user changes the email field to "new@example.com"
    And the user clicks "Save profile"
    Then the email field shows "new@example.com"
    And a [data-testid="profile-saved-toast"] is visible

  Scenario Outline: Email update validation rejects invalid input
    When the user changes the email field to "<invalid_email>"
    And the user clicks "Save profile"
    Then the email field shows the previous value
    And a [data-testid="email-validation-error"] is visible

    Examples:
      | invalid_email           |
      | not-an-email            |
      | missing@                |
      | @example.com            |
      | spaces in@email.com     |

Example 2: PRD with implicit preconditions

Input (PRD excerpt):

"We will allow promo codes at checkout. Codes apply 20% off the subtotal."

Output:

## Implicit-precondition flags (3)

1. **Code source.** Where do codes come from - user-entered? auto-applied? Both?
2. **Eligibility.** Are codes user-tier specific (e.g. only new users)?
   Time-limited? Per-user limited?
3. **Subtotal definition.** Subtotal *before* tax / shipping, or *after*?

Without these answers, the test suite cannot be written.

Never fabricate the missing pieces - return a question list to the PRD author instead.

Example 3: Scenario Outline opportunity

Input:

"Login should work for active accounts (returning 200) but reject suspended (401), unverified (403), and non-existent (404) accounts."

Output:

Feature: Login authorization

  Scenario Outline: Login response per account status
    Given an account with status "<status>"
    When the user submits valid credentials
    Then the response status is <http_status>
    And the response body contains "<error_code>"

    Examples:
      | status        | http_status | error_code           |
      | active        | 200         |                       |
      | suspended     | 401         | ACCOUNT_SUSPENDED    |
      | not_verified  | 403         | EMAIL_NOT_VERIFIED   |
      | not_found     | 404         | ACCOUNT_NOT_FOUND    |

Related skills

bdd-step-library-curator

Keeps a BDD step-definition library DRY across a Cucumber / Behave / Reqnroll project - inventories every step definition, detects duplicates (different patterns matching the same intent), recommends canonical consolidations, reorganizes steps by domain, publishes a step-library README the team greps for "is there already a step for X?" before authoring new ones, and builds a scenario coverage map that fingerprints new Gherkin scenarios against the live suite to classify each as duplicate, partial overlap, or genuine gap before any test is authored. Use when a BDD project's step count grows past ~50, on a quarterly step-library review, when a new engineer is about to write a duplicate step, or when fresh .feature files need a covered-already check.

behave-testing

Configures Behave for Python BDD scenarios - `pip install behave`, authors `.feature` files in Gherkin, writes step implementations in `features/steps/*.py`, configures via `environment.py` for setup/teardown hooks, organizes via tags, runs via `behave`. Use for Python codebases that want Cucumber-family BDD without Cucumber-Ruby / Cucumber-JS.

cucumber-testing

Configures Cucumber for BDD scenarios - Cucumber-JVM (Java/Kotlin via JUnit 5), Cucumber-JS (Node), Cucumber-Ruby. Authors `.feature` files in Gherkin, writes step definitions in the host language, runs via the framework's runner, integrates with JUnit XML reporting. Use when the user mentions Cucumber, Gherkin, `.feature` files, or behavior-driven (BDD) tests in Java, Kotlin, JavaScript, or Ruby, as the canonical wrapper for any of the three official implementations.

living-documentation-publisher

Converts passing Cucumber JSON output into stakeholder-facing living documentation: generates HTML reports via multiple-cucumber-html-reporter (Node) or Serenity BDD aggregate (JVM), applies Gherkin tags to drive report sections, and publishes to GitHub/GitLab Pages in CI. Use when BDD scenarios are in use and the team needs an always-current, non-test-engineer-readable document showing which acceptance criteria pass.

reqnroll-testing

Configures Reqnroll (the canonical .NET BDD framework) - install via `dotnet add package Reqnroll`, author `.feature` files in Gherkin, write step bindings as `[Given/When/Then]`-decorated methods in any C# class, runs via `dotnet test`. Reqnroll is the SpecFlow successor (SpecFlow reached end-of-life 2024-12-31); covers the SpecFlow-to-Reqnroll migration path, and references/specflow-legacy.md maintains not-yet-migrated SpecFlow projects. Use for .NET projects starting BDD, migrating from SpecFlow, or maintaining legacy SpecFlow suites.