Skip to main content

docs/feature_files.md

# Writing Feature Files

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:

```gherkin
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:

```gherkin
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:

```gherkin
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:

```gherkin
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:

```gherkin
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:

```gherkin
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:

```gherkin
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

```gherkin
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

```gherkin
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:

````gherkin
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:

```gherkin
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:`:

```gherkin
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](https://github.com/cucumber/gherkin/blob/main/MARKDOWN_WITH_GHERKIN.md)
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:

```markdown
# 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:

```gherkin
@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:

```gherkin
@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