Writing Feature Files

View Source

Feature 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 later

Background

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 available

Scenarios

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 item

Scenario 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 preconditions
  • When: Describes actions
  • Then: Specifies expected outcomes
  • And/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.98

Doc 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 recorded

Backticks 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 recorded

The 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 item

Rules

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 happen

Markdown 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 screen

File 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.feature

Tags

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 message

Tags 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 28

Use @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

  1. Keep language simple and consistent - Use clear, business-focused terminology
  2. One scenario per behavior - Each scenario should test one specific behavior
  3. Be specific in examples - Use concrete values rather than vague descriptions
  4. Use background wisely - Only for steps that are truly common to all scenarios
  5. Limit scenario length - If a scenario has many steps, consider breaking it down
  6. Organize with tags - Use tags to categorize and group related scenarios
  7. Think like a user - Write scenarios from the user's perspective
  8. Don't get too technical - Avoid technical implementation details in Gherkin