Gherkin Syntax Mastery
All keywords, Background, Tags, Rule, doc strings
The Complete Gherkin Keywords
Gherkin has a small but powerful set of keywords. Here’s every single one with its purpose:
| Keyword | Purpose | Required? |
|---|---|---|
Feature | Names and describes the feature under test | Yes (one per file) |
Scenario | Defines a single test case | Yes (at least one) |
Given | Precondition — sets up the context | No, but recommended |
When | Action — the event being tested | No, but recommended |
Then | Outcome — the expected result | No, but recommended |
And | Continues the previous Given/When/Then | No |
But | Negative continuation (reads better for exclusions) | No |
Background | Shared steps that run before every scenario | No |
Scenario Outline | Template for data-driven scenarios | No |
Examples | Data table for Scenario Outline | Required with Outline |
Rule | Groups related scenarios under a business rule | No (Cucumber 6+) |
@tag | Labels for filtering and organizing | No |
# | Comment line | No |
""" | Doc string (multi-line text) | No |
| ` | ` | Data table row delimiter |
Feature & Scenario
Feature Block
Every .feature file starts with exactly one Feature: keyword:
Feature: Shopping Cart Management
As an online shopper
I want to manage items in my cart
So that I can purchase what I need
The description lines (As a / I want / So that) are optional free text. Cucumber ignores them — they’re purely for human readers. You can write any description you like:
Feature: Password Reset
This feature covers all password reset scenarios including
email verification, security questions, and token expiration.
Priority: High | Sprint: 24.3 | Owner: QA Team
Scenario Block
Each Scenario represents one specific test case with a clear name that describes what’s being tested:
Feature: User Registration
Scenario: Successful registration with all required fields
Given I am on the registration page
When I fill in the registration form with valid data
And I accept the terms and conditions
And I click the register button
Then I should see a confirmation message
And I should receive a verification email
Scenario: Registration fails without email
Given I am on the registration page
When I fill in the form without an email
And I click the register button
Then I should see an error "Email is required"
Background — Shared Setup
When every scenario in a feature file starts with the same steps, use Background to avoid repetition:
Without Background (Repetitive)
Feature: Shopping Cart
Scenario: Add item to cart
Given I am logged in as a customer
And I am on the products page
When I add "Laptop" to the cart
Then the cart should contain 1 item
Scenario: Remove item from cart
Given I am logged in as a customer
And I am on the products page
When I add "Laptop" to the cart
And I remove "Laptop" from the cart
Then the cart should be empty
With Background (Clean)
Feature: Shopping Cart
Background:
Given I am logged in as a customer
And I am on the products page
Scenario: Add item to cart
When I add "Laptop" to the cart
Then the cart should contain 1 item
Scenario: Remove item from cart
When I add "Laptop" to the cart
And I remove "Laptop" from the cart
Then the cart should be empty
Tags — Organize and Filter
Tags let you categorize, filter, and selectively run scenarios. They start with @ and can be placed on Features, Scenarios, Scenario Outlines, and Examples tables.
Applying Tags
@regression
Feature: User Login
@smoke @priority-high
Scenario: Successful login
Given I am on the login page
When I login with valid credentials
Then I should see the dashboard
@negative @priority-medium
Scenario: Login with wrong password
Given I am on the login page
When I login with invalid password
Then I should see an error message
@wip
Scenario: Login with expired account
Given I have an expired account
When I try to login
Then I should see "Account expired" message
Tag Inheritance
Tags on the Feature line are inherited by all scenarios in that file. In the example above, every scenario automatically has @regression.
Running with Tags
// In TestRunner
@CucumberOptions(
features = "src/test/resources/features",
glue = "com.gyancode.cucumber.stepdefinitions",
tags = "@smoke and not @wip"
)
# From command line
mvn test -Dcucumber.filter.tags="@smoke"
mvn test -Dcucumber.filter.tags="@smoke and @login"
mvn test -Dcucumber.filter.tags="@smoke or @regression"
mvn test -Dcucumber.filter.tags="not @wip"
mvn test -Dcucumber.filter.tags="(@smoke or @regression) and not @skip"
Common Tag Strategies
| Tag | Purpose |
|---|---|
@smoke | Critical path tests — run on every build |
@regression | Full regression suite — run nightly |
@wip | Work in progress — skip in CI |
@negative | Negative/error scenarios |
@api | API-only tests (no UI) |
@slow | Long-running tests |
@JIRA-1234 | Linked to a specific ticket |
@sprint-24 | Tied to a development sprint |
Rule — Group by Business Rule
The Rule keyword (Cucumber 6+) groups scenarios that verify the same business rule. It adds a semantic layer between Feature and Scenario:
Feature: Account Withdrawal
Rule: Withdrawal is allowed when account has sufficient funds
Scenario: Withdraw within balance
Given my account balance is 500
When I withdraw 200
Then my new balance should be 300
Scenario: Withdraw exact balance
Given my account balance is 500
When I withdraw 500
Then my new balance should be 0
Rule: Withdrawal is denied when funds are insufficient
Scenario: Withdraw more than balance
Given my account balance is 500
When I try to withdraw 600
Then I should see "Insufficient funds"
And my balance should remain 500
Rule: Daily withdrawal limit is enforced
Scenario: Exceed daily withdrawal limit
Given my account balance is 10000
And the daily limit is 2000
When I try to withdraw 3000
Then I should see "Exceeds daily limit"
Doc Strings — Multi-line Text
When a step needs a large block of text (JSON body, email content, error message), use doc strings with triple quotes:
Scenario: Create user via API
Given the API is available
When I send a POST request to "/api/users" with body:
"""json
{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"role": "admin"
}
"""
Then the response status should be 201
In the step definition, the doc string is received as a String parameter:
@When("I send a POST request to {string} with body:")
public void sendPostRequest(String endpoint, String body) {
// 'body' contains the entire JSON block
response = given()
.contentType(ContentType.JSON)
.body(body)
.post(endpoint);
}
Doc Strings with Content Type
The content type hint after """ (like """json or """xml) is optional and is for readability. Cucumber passes the raw text regardless.
Scenario: Verify email content
When the system sends a welcome email
Then the email body should contain:
"""
Dear John,
Welcome to our platform! Your account has been
successfully created.
Best regards,
The Team
"""
Data Tables — Structured Data in Steps
Data tables pass structured data to a step. They’re defined with pipe characters (|) right after a step:
Scenario: Register a new user
When I fill in the registration form:
| field | value |
| firstName | John |
| lastName | Doe |
| email | john@example.com |
| password | SecurePass123 |
Then the registration should be successful
Different Table Shapes
Key-Value Pairs (2 columns)
When I configure the settings:
| timeout | 30 |
| retries | 3 |
| headless | true |
Single Column (List)
Then the following items should be in the cart:
| Laptop |
| Mouse |
| Keyboard|
Multiple Rows with Headers
When I create the following users:
| username | email | role |
| john | john@test.com | admin |
| jane | jane@test.com | user |
| bob | bob@test.com | viewer |
Comments and Descriptions
Comments
Lines starting with # are comments and are ignored by Cucumber:
# This feature covers the payment processing module
# Last updated: Feb 2026 by QA team
Feature: Payment Processing
# Positive scenarios
Scenario: Successful credit card payment
Given I have items in my cart
# TODO: Add step for applying discount code
When I pay with a valid credit card
Then the payment should be processed
Descriptions
Free-form text after Feature, Scenario, Rule, or Background names:
Feature: Inventory Management
Manages product stock levels, reorder alerts,
and warehouse allocation.
Scenario: Low stock alert triggers notification
When a product drops below the reorder threshold,
the system should notify the warehouse manager.
Given "Widget A" has a reorder threshold of 10
And the current stock of "Widget A" is 15
When 6 units of "Widget A" are sold
Then a low stock alert should be sent
Scenario Outline — A Quick Preview
When you want to run the same scenario with multiple data sets, use Scenario Outline with Examples:
Feature: Login Validation
Scenario Outline: Login with different credentials
Given I am on the login page
When I enter username "<username>"
And I enter password "<password>"
And I click login
Then I should see "<result>"
Examples:
| username | password | result |
| validuser | validpass | Welcome |
| invaliduser | validpass | Invalid credentials |
| validuser | wrongpass | Invalid credentials |
| | validpass | Username required |
| validuser | | Password required |
This generates 5 separate scenarios, one for each row in the Examples table. The angle brackets (<username>) are placeholders that get replaced with values from each row.
Feature File Organization
Recommended Folder Structure
src/test/resources/features/
├── authentication/
│ ├── login.feature
│ ├── logout.feature
│ ├── password_reset.feature
│ └── registration.feature
├── shopping/
│ ├── cart.feature
│ ├── checkout.feature
│ ├── product_search.feature
│ └── wishlist.feature
├── user_management/
│ ├── profile.feature
│ ├── settings.feature
│ └── notifications.feature
└── api/
├── user_api.feature
├── product_api.feature
└── order_api.feature
Feature File Naming Conventions
| Convention | Example |
|---|---|
| Use snake_case or kebab-case | password_reset.feature |
| Name by feature, not by page | checkout.feature not checkout_page.feature |
| One feature per file | Don’t mix login and registration in one file |
| Group by business domain | shopping/, authentication/ |
| Keep scenarios under 10 per file | Split large features into sub-features |
A Well-Organized Feature File
@authentication @regression
Feature: User Login
Validates the login functionality for registered users
including successful login, failed attempts, and account lockout.
Background:
Given the application is running
And I am on the login page
@smoke @priority-high
Scenario: Successful login with valid credentials
When I login with valid credentials
Then I should see the dashboard
And the last login time should be updated
@negative
Scenario: Login fails with incorrect password
When I login with incorrect password
Then I should see "Invalid credentials"
But I should remain on the login page
@negative @security
Scenario: Account locks after 5 failed attempts
When I attempt login with wrong password 5 times
Then my account should be locked
And I should see "Account locked. Try again in 30 minutes."