Gherkin is the language behind BDD: a small set of keywords that makes a test scenario readable by anyone, from the Product Owner to the developer, and at the same time executable by tools like Cucumber, Behave (Python), SpecFlow (.NET), or Behat (PHP). It's the point where the specification and the test become the same document.
The keywords
The whole grammar fits in a few words. The rest is free text that you choose:
- Feature — the grouping; describes a capability of the system.
- Scenario — a concrete example of behavior.
- Given — the context / precondition. The world before the action.
- When — the action that triggers the behavior. Just one per scenario, ideally.
- Then — the observable outcome that gets verified.
- And / But — chain steps of the same type, keeping the reading fluid.
The Given-When-Then structure
The heart of Gherkin is separating context → action → outcome. This triad forces the author to think about behavior, not screens:
# language: en
Feature: User authentication
Scenario: Login with valid credentials
Given I am on the login page
And I have an account with the email "ana@example.com"
When I enter the correct credentials
Then I should see the dashboard
And I should see the greeting "Hello, Ana"
Golden rule: Given has no action, When is a single action, Then has no side effects, it only verifies. If a scenario has three "When"s, it's probably three scenarios in disguise.
Background: the context that repeats
When several scenarios share the same Givens, the Background avoids repetition; it runs before each scenario in the file:
Background:
Given I am logged in as an administrator
And a product "Notebook" exists in the catalog
Scenario Outline: one scenario, lots of data
To test the same rule with several inputs (the classic case of equivalence partitioning and boundary values), use the Scenario Outline with an Examples table:
Scenario Outline: Discount by order value
Given a cart with <value> dollars
When the customer checks out
Then the total charged should be <total> dollars
Examples:
| value | total |
| 100 | 100 |
| 101 | 90.9 |
| 150 | 135 |
Each row of the table becomes an independent scenario. It's the cleanest way to cover boundaries (the 100 that gets no discount and the 101 that does) without copy and paste.
From text to code: step definitions
Gherkin alone tests nothing; it gets "glued" to the system by step definitions: functions that match each step by expression and run the actual automation. In Cucumber with JavaScript:
const { Given, When, Then } = require('@cucumber/cucumber');
const { expect } = require('@playwright/test');
Given('a cart with {int} dollars', async function (value) {
this.cart = createCart(value);
});
When('the customer checks out', async function () {
this.total = this.cart.checkout();
});
Then('the total charged should be {float} dollars', async function (expected) {
expect(this.total).toBeCloseTo(expected, 2);
});
Notice that the same step a cart with {int} dollars serves every row of the Examples. Well-written steps are reusable, and that's BDD's maintenance payoff.
Declarative > imperative
The most common mistake is writing imperative scenarios that describe every click. They break with every screen tweak and nobody on the business side can read them:
| Imperative (brittle) | Declarative (robust) |
|---|---|
| When I fill in the "email" field with "ana@x.com" And I fill in the "password" field with "123" And I click the "#btn-login" button |
When I log in with valid credentials |
The "how to fill in the form" belongs to the step definition (and to the Page Object), not to Gherkin. The scenario describes the intent.
Anti-patterns to watch for
- Soap-opera scenario: ten steps covering an entire flow. One scenario = one behavior.
- UI detail in the Then: verifying a button's color or CSS. Verify a business outcome.
- Coupling between scenarios: scenario 2 depending on the state left by scenario 1. Each one must be independent.
- Gherkin without conversation: writing the
.featurefiles alone, after the implementation. That's just a dressed-up report, and you lose the discovery value of BDD.
Conclusion
Gherkin is simple on purpose: the vocabulary restriction is what keeps the scenario readable for everyone and stable over time. Mastering Given-When-Then, Background, and Scenario Outline, and knowing how to write declaratively, is what turns a BDD suite into living documentation instead of one more set of brittle tests.