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 paidandThen the invoice is paidare 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.
Read next
- 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.