Macros

Create reusable, parameterized test patterns with macros

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 StepData Table RowInternal MapResult
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 @macro tag 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 --verbose flag for debugging

Next Steps