# 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
```
## File Organization
Feature files should be placed in a `test/features/` directory and have a `.feature` extension. 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