Macros
Macros in TestFlowKit are reusable, parameterized test scenarios that help reduce code duplication and improve maintainability.
What are Macros?
Macros allow you to define common test patterns once and reuse them across multiple test scenarios with different data sets.
Key Benefits
- ✅ Parameterized Reusability — Use the same macro with different data
- ✅ Table-Driven Testing — Easy to test multiple scenarios with different parameters
- ✅ Improve Maintainability — Update logic in one place, affects all usages
- ✅ Better Organization — Separate macro definitions from test scenarios
How Macros Work
1. Define a Macro
Create a scenario with the @macro tag and use ${variable_name} syntax for placeholders:
@macro
Scenario: Login as user
Given the user goes to the "login" page
When the user enters "${email}" into the "email" field
And the user enters "${password}" into the "password" field
And the user clicks the "login" button
Then the page title should be "Dashboard"
2. Use the Macro
Invoke the macro with a data table containing variable-value pairs. Each row contains a variable name and its value:
Scenario: Admin can access dashboard
Given Login as user
| email | admin@example.com |
| password | admin123 |
When the user clicks the "admin_panel" link
Then the "admin_dashboard" should be visible
Data Table Format:
- Two-column layout: Each row has
[variable_name, value] - First column: Variable name corresponding to
${variable_name}placeholders - Second column: Variable value that will be substituted into the macro
- TestFlowKit internally converts each row to a map entry for efficient variable substitution
Macro Syntax
Defining Variables
Use ${variable_name} to define placeholders in your macro:
@macro
Scenario: Fill contact form
When the user enters "${name}" into the "name" field
And the user enters "${email}" into the "email" field
And the user enters "${message}" into the "message" field
And the user clicks the "submit" button
Invoking Macros
Call the macro using its scenario name followed by a data table. Each row contains a variable name and its value:
Scenario: Submit support request
Given the user goes to the "contact" page
When Fill contact form
| name | John Doe |
| email | john@example.com |
| message | I need help with login |
Then the "success_message" should be visible
Key Points:
- Each table row defines one variable:
[variable_name, value] - Variables are mapped internally as key-value pairs
- Example above creates map:
{name: "John Doe", email: "john@example.com", message: "I need help with login"}
Variable Substitution
Variables are replaced at runtime using a map created from the data table. Each row provides a key-value pair:
| Macro Step | Data Table Row | Internal Map | Result |
|---|---|---|---|
the user enters "${email}" | | email | john@example.com | | {email: "john@example.com"} | the user enters "john@example.com" |
Example:
When Login as user
| email | user@example.com | ← Row 1: email = user@example.com
| password | secret123 | ← Row 2: password = secret123
Internally maps to: {email: "user@example.com", password: "secret123"}
Real-World Examples
Login Macros
# macros/auth.feature
@macro
Scenario: Login with credentials
Given the user goes to the "login" page
When the user enters "${email}" into the "email" field
And the user enters "${password}" into the "password" field
And the user clicks the "login" button
Then the "dashboard" should be visible
@macro
Scenario: Logout
When the user clicks the "user_menu" button
And the user clicks the "logout" link
Then the "login" page should be visible
Usage:
Scenario: User session management
Given Login with credentials
| email | user@example.com |
| password | userpass123 |
Then the "welcome_message" should contain "Welcome"
When Logout
Then the current URL should contain "/login"
Data Setup Macros
@macro
Scenario: Create product via API
Given I prepare a request for the "create_product" endpoint
And I set the request body to:
"""
{
"name": "${product_name}",
"price": ${price},
"category": "${category}"
}
"""
When I send the request
Then the response status code should be 201
Usage:
Scenario: Verify product catalog
Given Create product via API
| product_name | Laptop Pro |
| price | 999 |
| category | Electronics |
And Create product via API
| product_name | Office Chair |
| price | 299 |
| category | Furniture |
When the user goes to the "products" page
Then the "product_list" should contain "Laptop Pro"
And the "product_list" should contain "Office Chair"
Form Submission Macros
@macro
Scenario: Complete checkout
Given the user goes to the "checkout" page
When the user enters "${card_number}" into the "card" field
And the user enters "${expiry}" into the "expiry" field
And the user enters "${cvv}" into the "cvv" field
And the user selects "${country}" from the "country" dropdown
And the user clicks the "pay_button" button
Then the "confirmation" should be visible
Usage:
Scenario: Purchase with US credit card
# ... add items to cart ...
When Complete checkout
| card_number | 4111111111111111 |
| expiry | 12/25 |
| cvv | 123 |
| country | United States |
Then the "order_number" should be visible
Organizing Macros
File Structure
features/
├── macros/
│ ├── auth.feature # Login/logout macros
│ ├── data-setup.feature # API data creation macros
│ └── checkout.feature # E-commerce macros
├── login/
│ └── login.feature # Login tests
└── checkout/
└── purchase.feature # Checkout tests
Naming Conventions
- ✅ Use descriptive names that indicate the macro's purpose
- ✅ Start with a verb: "Login as", "Create", "Fill", "Complete"
- ✅ Keep names concise but clear
Best Practices
Do's
- ✅ Keep macros focused on single responsibilities
- ✅ Use descriptive variable names
- ✅ Group related macros in the same file
- ✅ Document variable requirements
- ✅ Test macros with different variable combinations
- ✅ Limit to 2-5 variables per macro
Don'ts
- ❌ Don't create overly complex macros
- ❌ Don't use unclear variable names
- ❌ Don't mix macro definitions with test scenarios
- ❌ Don't create macros too specific to one use case
- ❌ Don't ignore macro reusability
Troubleshooting
Macro Not Found
Problem: TestFlowKit can't find your macro
Solutions:
- Verify the
@macrotag is present - Check the scenario name matches exactly
- Ensure the macro file is in the features directory
Variable Not Substituted
Problem: ${variable} appears literally in test output
Solutions:
- Verify variable name in data table matches the placeholder
- Check for typos in variable names
- Ensure data table is properly formatted
Wrong Values Used
Problem: Variables have unexpected values
Solutions:
- Check data table row/column alignment
- Verify variable names are unique
- Use
--verboseflag for debugging
Next Steps
- Global Hooks — Setup and teardown across test suites
- Frontend Testing — Browser automation features
- API Testing — REST API testing