Specroot Waitlist open

Gherkin examples

Gherkin is a plain-text language for describing how software should behave through concrete examples — Feature, Scenario, Given, When, Then — in .feature files that tools such as Cucumber run as tests. Below are the keywords, a full feature file, a template, Scenario Outline with Examples, data tables, Background and Rule, login and API examples, the practices that keep scenarios readable, and when Gherkin is worth the effort.

Cucumber is not a tool for testing software. It is a tool for testing people’s understanding of how software (yet to be written) should behave.

— Aslak Hellesøy, creator of Cucumber, on Hacker News, 2015

Given/When/Then comes from behaviour-driven development (BDD). Dan North and the business analyst Chris Matts made it a template for a story’s acceptance criteria: “Given some initial context (the givens), When an event occurs, Then ensure some outcomes” (Introducing BDD, 2006). Gherkin is the language Cucumber uses to write such scenarios down (Wikipedia), and its keywords have been translated into over 70 spoken languages (Cucumber).

Gherkin syntax: the keywords

Keyword What it does
Feature: Names one feature and groups its scenarios. The first keyword in the file; one per file
Rule: Groups the scenarios that illustrate one business rule (since Gherkin 6)
Background: Given steps that run before every scenario in the feature or rule
Scenario: or Example: One concrete example, as a list of steps
Given The starting state: what is true before anything happens
When The event or the action
Then The outcome someone can see
And, But, * One more step of the same kind as the one before
Scenario Outline: A scenario that runs once per row of its Examples; also Scenario Template:
Examples: The table of values for an outline; also Scenarios:
""" A doc string: a block of text passed to one step
| A data table passed to one step
@ A tag, above a feature, rule, scenario, outline or Examples
# A comment, on a line of its own

Three rules catch people out:

  • Every line starts with a keyword, apart from comments, table and doc string lines, and the free text under a Feature, Rule, Background or Scenario line.
  • Colons matter. Feature, Rule, Background, Scenario, Scenario Outline and Examples take one; Given, When, Then, And and But do not. The Cucumber reference warns: “If you add a colon after a keyword that should not be followed by one, your test(s) will be ignored.”
  • The keyword is not part of the step. Cucumber matches a step by its text alone, so Given the invoice is paid and Then the invoice is paid are the same step. Make them different: Given INV-2041 was paid by transfer, Then INV-2041 is marked "Paid" today.

Gherkin feature file example

The customer portal from the other templates: requirement FR-014, a finance clerk paying an open invoice by card. The file is features/pay-invoice-by-card.feature.

@FR-014
Feature: Pay an open invoice by card
  A finance clerk pays an open invoice
  by card, so that it is paid sooner.

  Background:
    Given a finance clerk is signed in
    And INV-2041 is open for 1,250.00 EUR

  Scenario: A card the bank approves
    Given a card the bank approves
    When the clerk pays INV-2041 with it
    Then INV-2041 is marked "Paid" today
    And a receipt is emailed to the clerk

  Scenario: A card the bank declines
    Given a card the bank declines
    When the clerk pays INV-2041 with it
    Then the clerk sees the bank's reason
    And INV-2041 is still open
    But no payment is recorded

  Scenario: Paid by transfer meanwhile
    Given INV-2041 was paid by transfer
    When the clerk pays INV-2041 by card
    Then the clerk sees it is already paid
    And no card payment is taken

  @slow
  Scenario: The bank does not answer
    Given a bank that does not answer
    When the clerk pays INV-2041 by card
    Then INV-2041 shows "Payment pending"
    And the card is charged at most once

Each scenario is one outcome, with one When. Together they are the main flow and the extensions 1a, 5a and 5b of the use case template, and the declined card is test case TC-102 from the test case template — written once, in words the client can read, and run as a test.

The tags do two jobs. @FR-014 ties the file to its requirement: Cucumber’s documentation notes that tags “can refer to IDs in external systems such as requirement management tools, issue trackers or test management tools”. @slow marks the scenario that waits for the bank, so the team can leave it out of a quick run with cucumber --tags "not @slow".

Gherkin template

Copy it into a .feature file. Square brackets are yours to fill in; keep the keywords and colons as they are.

@[requirement ID]
Feature: [what the user can do]
  [Why it matters, and for whom. Free
  text, up to the first keyword.]

  Background:
    Given [state every scenario shares]

  Scenario: [the normal case]
    Given [the starting state]
    When [one action or event]
    Then [a result someone can see]
    And [another visible result]

  Scenario: [an error or a refusal]
    Given [   ]
    When [   ]
    Then [   ]

  Scenario Outline: [a rule, many values]
    Given [a state with <input>]
    When [one action]
    Then [a result with <expected>]

    Examples:
      | input | expected |
      | [   ] | [      ] |

Scenario Outline and Examples

A Scenario Outline runs the same steps once for each row of its Examples table; each <name> in the steps takes the value from that column. Requirement FR-016 says the portal emails a reminder seven days after an invoice’s due date:

Scenario Outline: Reminder after due date
  Given an invoice due on 1 June
  And the invoice is <status>
  When the date is <date>
  Then <emails> reminder is emailed

  Examples:
    | status | date   | emails |
    | open   | 7 June | no     |
    | open   | 8 June | one    |
    | paid   | 8 June | no     |

Three rows, three runs: the day before the reminder is due, the day it is due, and an invoice already paid.

Scenario vs Scenario Outline: use an outline when only the values change. If a row needs a different step, it is a different scenario. An outline can have more than one Examples table, each with its own tags — one set of rows for phones and one for desktop, for example.

Data tables

A data table passes a list to one step. Unlike an Examples table, it does not repeat the scenario: the scenario runs once, with the whole table. Requirement FR-010 says a customer sees their own company’s invoices:

Scenario: Only your company's invoices
  Given these invoices:
    | invoice  | company | status |
    | INV-2041 | Acme    | open   |
    | INV-2042 | Acme    | paid   |
    | INV-2043 | Birch   | open   |
  When an Acme user opens the list
  Then they see INV-2041 and INV-2042
  But they do not see INV-2043
Aspect Data table Scenario Outline with Examples
Runs the scenario Once Once per row
The table belongs to One step The whole scenario
Use it for Things that exist together The same rule with different values

Background and Rule

Background holds the Given steps every scenario in the file shares — the signed-in clerk and the open invoice in the feature file above — and runs them before each scenario. A feature or a rule can have one. Cucumber’s reference suggests that if it is “more than 4 lines long, consider moving some of the irrelevant details into higher-level steps”.

Rule groups the scenarios that illustrate one business rule. The rules are the acceptance criteria; the scenarios under each are its examples. The reminder requirement again, written with rules:

Feature: Payment reminders

  Rule: Remind seven days after due date

    Example: Not yet seven days
      Given an open invoice due on 1 June
      When the date is 7 June
      Then no reminder is emailed

    Example: Seven days late
      Given an open invoice due on 1 June
      When the date is 8 June
      Then one reminder is emailed

  Rule: Paid invoices get no reminder

    Example: Paid before the reminder
      Given an invoice due on 1 June
      And it was paid on 5 June
      When the date is 8 June
      Then no reminder is emailed

Example is another name for Scenario; under a Rule it reads more naturally.

More Gherkin examples: login and API

Sign in, with the rules from the login test cases on the test case template:

Scenario: Right email and password
  Given a customer with an active account
  When they sign in correctly
  Then they see their account overview

Scenario Outline: Sign-in refused
  When someone signs in with <entry>
  Then they are not signed in
  And "Email or password is wrong" shows

  Examples:
    | entry                      |
    | a wrong password           |
    | an email nobody registered |

Scenario: Locked after five wrong tries
  Given four wrong passwords in 15 minutes
  When a fifth wrong password is entered
  Then the account locks for 15 minutes
  And the customer gets an email about it

The outline checks that a wrong password and an unknown email get the same message, so the page does not tell anyone which emails have an account.

An API test, with a doc string:

Scenario: Read an open invoice
  Given INV-2041 is open for 1,250.00 EUR
  When the client requests INV-2041
  Then the response status is 200
  And the response body is:
    """json
    {
      "id": "INV-2041",
      "status": "open",
      "amount": "1250.00",
      "currency": "EUR"
    }
    """

Scenario: Another company's invoice
  Given another company owns INV-2043
  When the client requests INV-2043
  Then the response status is 404

The text between the """ lines is passed to the step as one block, and json names what it contains. The URL and the headers live in the step definitions; the scenario keeps what the API promises.

Gherkin best practices

Most of the advice comes down to one question from Cucumber’s guide to writing better Gherkin: “Will this wording need to change if the implementation does?” If the answer is yes, rewrite the step.

Imperative — every click (avoid):

Scenario: Pay an invoice
  Given I am on "/invoices/INV-2041"
  When I click "Pay by card"
  And I type "4242 4242 4242 4242"
  And I click "Pay now"
  Then the "status" cell says "Paid"

Declarative — the behaviour:

Scenario: Pay an invoice
  Given a card the bank approves
  When the clerk pays INV-2041 with it
  Then INV-2041 is marked "Paid" today

The first breaks when a button is renamed; the second only when the behaviour changes. One commenter: “There’s way to much Gherkin out there which tries to use it for describing a journey (I click this, then this, and this....)” (Hacker News, 2022).

  • One behaviour per scenario. One When. Two actions with two results are two scenarios.
  • Three to five steps. The Cucumber reference recommends “3-5 steps per example”.
  • Given is a state, not a journey. In the reference’s words: “If you were creating use cases, Given’s would be your preconditions.”
  • Then is something someone can see: a screen, a message, an email. The reference: “An outcome should be on an observable output” — not a record in a database.
  • The business’s words. If the client says “invoice” and the code says “billing document”, the scenario says “invoice”.
  • Only the data that matters. The 1,250.00 EUR matters to the scenario; the test user’s email address does not.
Weak step What is wrong Better
When I click “Pay now” The screen, not the behaviour When the clerk pays INV-2041 by card
Then a row is added to payments Nobody can see it Then INV-2041 is marked “Paid” today
Given I log in as test1 with Secret123 Data nobody needs Given a finance clerk is signed in
Then it works Cannot fail Then the clerk sees the bank’s reason
When the clerk pays, downloads the PDF and signs out Three behaviours in one Three scenarios, one When each

Gherkin, acceptance criteria and user stories

A user story says who wants what and why; its acceptance criteria are the rules; Gherkin scenarios are examples of each rule. A rule can itself be one sentence in EARS. Cucumber’s Example Mapping lays this out on cards: the story on a yellow card, each rule on a blue card under it, examples on green cards under each rule, and open questions on red cards.

Teams disagree on where the scenarios live. One commenter keeps them out of the story: Gherkin is “a language for writing test scenarios that should pass if an acceptance criteria is met”, and “It belongs in a test suite in source control along with your code” (r/agile, 2023). Another writes the scenario into the story: “That scenario is essentially both a test case and part of the acceptance criteria” (r/agile, 2022).

Either works while there is one copy. With two — the story in Jira and the .feature file in the repository — the first edit to one of them starts the spec drift. The acceptance criteria template has the Given/When/Then and checklist formats for the story itself; the user story template has the story.

Gherkin in Jira

In Jira, the scenarios can go in the story’s description or in an acceptance criteria field, as plain text. If they live in .feature files instead, tag each scenario with the issue key — @PAY-41 — so that each scenario points back to its story, and the story says where its scenarios are.

Gherkin vs Cucumber: the tools that run it

Gherkin is the language; Cucumber is a tool that runs it. Each step is matched to a step definition — a piece of code that does what the step says and checks the result. Cucumber’s list of implementations, for the main languages:

Language Tool On Cucumber’s list as
JavaScript Cucumber-JS Official
Java, Kotlin Cucumber-JVM Official
Ruby Cucumber-Ruby Official
.NET Reqnroll Semi-official
Python Behave, pytest-bdd Semi-official
PHP Behat Semi-official

Cucumber recommends “choosing an implementation for the same platform or programming language as the production code” (Cucumber). Reqnroll “has been created as a reboot of the SpecFlow project” (Reqnroll).

Is Gherkin worth it?

Gherkin’s promise is that people outside engineering read the scenarios and agree to them. Where they do, it works: “It works really well for us to get a shared understanding between a non-technical business, devs and QA” (Hacker News, 2022).

Where they do not, it is a layer of extra work. Someone who tried to introduce Cucumber “a couple of different times”:

The preconditions are that you have domain experts or business people interested and willing to engage in writing or reviewing these tests. Unless you have this and it’s something that those people are going to sustain when the going gets tough you’re just making writing tests harder for no real benefit.

— Hacker News, 2025

Another: “Don’t think I ever once saw a product owner take interest in a human readable test case” (Hacker News, 2023). And someone who spent “a fair number of years doing corporate cucumber training”: “Don’t go to the trouble of writing gherkin if you’re not using it as living documentation. Save yourself loads of trouble and just use an ordinary test framework.” (Hacker News, 2022).

So the question before adopting Gherkin is who outside the team will read the scenarios and say yes to them. If nobody will, well-named tests in your usual framework do the same job with one layer less.

Gherkin and AI coding agents

Scenarios give an AI coding agent a target it can check: it writes code until the scenarios pass. Spec-driven development tools use the same shape — Spec Kit’s spec template writes acceptance scenarios as “Given [initial state], When [action], Then [expected outcome]” (Spec Kit).

One developer experimenting with Cucumber: “you can write the .feature files first and have an LLM write the unit test code that interprets them” (Hacker News, 2026). Another skips the step definitions and has an AI agent carry out each step in a browser, “like human QA would”, while staying “cautious with letting AI ‘interpret’ how to execute each step” (Hacker News, 2026).

The risk is the one BDD set out to remove. One commenter, on engineers who write their own tests: “if the engineer misunderstands how the feature is supposed to work, then both the code and tests will be wrong, but because they are consistently wrong the tests will be green” (Hacker News, 2021). An agent that writes both the scenarios and the code can make the same mistake twice. And asking it to write the scenarios saves less than it seems: “By the time you have written enough to lower the risk of the AI getting it wrong, you have already written enough that people should know what is required” (r/agile, 2023). The scenarios still need someone who knows what was asked for to read them and agree.

Where Specroot fits

This is the problem Specroot works on: scenarios that stay tied to the requirement and the version that was agreed, so that when a requirement changes, the scenarios written for the old one are found and not left passing. Specroot for teams using AI coding agents.

  • Acceptance criteria template: Given/When/Then examples — Free acceptance criteria templates (Given/When/Then and checklist), with examples for user stories and APIs, and how they differ from the definition of done.
  • Test case template and examples — A free test case template to copy into a spreadsheet, with examples for a payment and a login page, positive and negative cases, and how to write test cases.
  • User story template and examples — A free user story template with acceptance criteria, software examples, a Jira version, INVEST, splitting, and user story vs use case, epic and task.
What Specroot is