Writing Feature Files
View SourceFeature files are the heart of Cucumber testing. They're written in Gherkin syntax, a business-readable domain-specific language that lets you describe application behavior without detailing how that behavior is implemented.
Feature File Structure
Feature files consist of several components:
Feature
Every feature file starts with the Feature: keyword followed by a name and optional description:
Feature: Shopping Cart
As a user
I want to add items to my cart
So that I can purchase them laterBackground
The Background: section contains steps that are executed before each scenario:
Background:
Given I am logged in as a customer
And the product catalog is availableScenarios
Scenarios are concrete examples of how the feature should behave:
Scenario: Adding an item to an empty cart
Given I am on the product page for "Ergonomic Keyboard"
When I click "Add to Cart"
Then I should see "Item added to cart" message
And my cart should contain 1 itemScenario Outlines
Scenario Outlines let you run the same scenario multiple times with different data. Use <placeholders> in step text and provide values in an Examples: table:
Scenario Outline: Adding items to cart
Given I have <count> items in my cart
When I add another <product>
Then I should have <total> items
Examples:
| count | product | total |
| 0 | Laptop | 1 |
| 2 | Headphones | 3 |Each row in the Examples table generates a separate test case.
Named Examples
Give Examples blocks descriptive names:
Scenario Outline: User authentication
Given I enter "<username>" and "<password>"
Then I should see "<result>"
Examples: valid credentials
| username | password | result |
| alice | secret | Welcome |
Examples: invalid credentials
| username | password | result |
| alice | wrong | Access denied|Tagged Examples
Apply tags to specific Examples blocks:
Scenario Outline: Payment processing
Given I pay with <method>
Then the payment should <status>
@smoke
Examples: common methods
| method | status |
| credit_card | succeed |
@slow @integration
Examples: alternative methods
| method | status |
| paypal | succeed |
| bitcoin | succeed |Tags on Examples blocks combine with tags on the Scenario Outline.
Placeholders in Step Arguments
Placeholders also work in doc strings and data tables:
Scenario Outline: Email templates
Given I send an email with body:
"""
Hello <name>,
Your order #<order_id> has shipped.
"""
Then the email should be sent
Examples:
| name | order_id |
| Alice | 12345 |Steps
Steps use keywords like Given, When, Then, And, and But:
Given: Establishes preconditionsWhen: Describes actionsThen: Specifies expected outcomesAnd/But: Continues the previous step type
Step Arguments
Gherkin supports several types of step arguments:
Data Tables
Scenario: Adding multiple items to cart
Given I have the following items in my cart:
| Product Name | Quantity | Price |
| Smartphone | 1 | 699.99|
| Protection Plan | 1 | 79.99 |
When I proceed to checkout
Then the total should be 779.98Doc Strings
Scenario: Submit feedback
When I submit the following feedback:
"""
I really like your product, but I think
it could be improved by adding more features.
Keep up the good work!
"""
Then my feedback should be recordedBackticks work as an alternative delimiter, and either delimiter may carry a media type annotation after the opening line:
Scenario: Submit structured feedback
When I submit the following feedback:
```json
{"rating": 5, "comment": "Keep up the good work!"}
```
Then my feedback should be recordedThe content arrives in your step as context.docstring; the media type (if
given) as context.docstring_media_type.
Descriptions
Free-form description text can follow any section header — Feature:,
Background:, Scenario:, Scenario Outline:, or Examples: — until the
first step, tag, or table row. Descriptions are purely informational and never
affect execution:
Scenario: Adding an item to an empty cart
Carts start empty for new sessions, so this is the
most common path through checkout.
Given I am on the product page for "Ergonomic Keyboard"
When I click "Add to Cart"
Then my cart should contain 1 itemRules
The Rule: keyword groups related scenarios under a business rule. A rule can
have its own description, tags, and Background:; rule-background steps run
after the feature background for each scenario in the rule, and rule tags are
inherited by those scenarios. Example: is accepted as a synonym for
Scenario::
Feature: Chocolate sales
Rule: A sale cannot happen if the customer has no money
Background:
Given there are chocolate bars in stock
Example: Not enough money
Given the customer has 100 cents
When the customer tries to buy a 125 cent chocolate bar
Then the sale should not happenMarkdown Feature Files
Features can also be written as Markdown documents with a .feature.md
extension, following the Markdown with Gherkin
format. Headings carry the Gherkin keywords (at any heading level), steps are
bullet-list items, data tables are indented Markdown tables, docstrings are
fenced code blocks (the info string becomes the media type), tags are inline
code spans like `@wip`, and everything else — paragraphs, images,
links — is prose that renders on GitHub but never executes:
# Feature: Basic Calculator
Anything that isn't Gherkin — like this paragraph — is documentation.
## Rule: Addition is commutative
### Scenario: Adding two numbers
- Given I have entered 50 into the calculator
- And I have entered 70 into the calculator
- When I press add
- Then the result should be 120 on the screenFile Organization
Feature files should be placed in a test/features/ directory and have a .feature extension — or .feature.md for Markdown with Gherkin. Organize them logically by feature or domain area:
test/
└── features/
├── authentication/
│ ├── login.feature
│ └── registration.feature
├── shopping/
│ ├── cart.feature
│ └── checkout.feature
└── user_profile.featureTags
Tags are used to categorize scenarios and can be used for filtering which tests to run:
@authentication @important
Feature: User Login
@happy_path
Scenario: Successful login with valid credentials
Given I am on the login page
When I enter valid credentials
Then I should be logged in
@error_handling
Scenario: Failed login with invalid credentials
Given I am on the login page
When I enter invalid credentials
Then I should see an error messageTags can be used at the Feature level (applies to all scenarios) or at the Scenario level.
Special Tags
@async
The @async tag enables concurrent test execution for features that don't share state:
@async
Feature: Independent Calculator Operations
This feature can run concurrently with other async tests
Scenario: Addition
Given I have a calculator
When I add 5 and 3
Then the result should be 8
Scenario: Multiplication
Given I have a calculator
When I multiply 4 and 7
Then the result should be 28Use @async only for features that:
- Don't share state with other tests
- Don't rely on test execution order
- Are truly independent of other tests
Note: Database tests can safely run async when using Ecto's SQL sandbox in shared mode. For non-Ecto resources (files, external APIs, etc.), ensure they can handle concurrent access.
Best Practices for Feature Files
- Keep language simple and consistent - Use clear, business-focused terminology
- One scenario per behavior - Each scenario should test one specific behavior
- Be specific in examples - Use concrete values rather than vague descriptions
- Use background wisely - Only for steps that are truly common to all scenarios
- Limit scenario length - If a scenario has many steps, consider breaking it down
- Organize with tags - Use tags to categorize and group related scenarios
- Think like a user - Write scenarios from the user's perspective
- Don't get too technical - Avoid technical implementation details in Gherkin