Global Hooks

Setup and teardown operations across your test suite

Global Hooks

Global hooks allow you to run setup and teardown operations before and after your entire test suite, enabling cross-scenario data sharing and environment preparation.

What are Global Hooks?

Global hooks are special feature files that run at specific points in your test execution:

  • BeforeAll — Runs once before any test scenarios
  • AfterAll — Runs once after all test scenarios complete

Use Cases

  • ✅ Set up test data via API before tests run
  • ✅ Initialize global variables used across scenarios
  • ✅ Configure authentication tokens
  • ✅ Seed a database
  • ✅ Clean up test data after all tests complete

Creating Global Hooks

BeforeAll Hook

Create a feature file with the @BeforeAll tag:

@BeforeAll
Feature: Test Setup

  Scenario: Initialize test environment
    Given I prepare a request for the "login" endpoint
    And I set the request body to:
      """
      {
        "email": "test@example.com",
        "password": "testpass123"
      }
      """
    When I send the request
    And I save the response path "$.token" as global variable "auth_token"
    Then the response status code should be 200

  Scenario: Create test user
    Given I prepare a request for the "create_user" endpoint
    And I set the request header "Authorization" to "Bearer {{auth_token}}"
    And I set the request body to:
      """
      {
        "name": "Test User",
        "email": "testuser@example.com"
      }
      """
    When I send the request
    And I save the response path "$.data.id" as global variable "test_user_id"
    Then the response status code should be 201

AfterAll Hook

Create a feature file with the @AfterAll tag:

@AfterAll
Feature: Test Cleanup

  Scenario: Delete test user
    Given I prepare a request for the "delete_user" endpoint
    And I set the following path parameters:
      | id | {{test_user_id}} |
    And I set the request header "Authorization" to "Bearer {{auth_token}}"
    When I send the request
    Then the response status code should be 204

  Scenario: Log completion
    Given I store the "completed" into "test_status" variable

Global Variables

Storing Global Variables

Use the global variable step to store data that persists across all scenarios:

# From API response
And I save the response path "$.token" as global variable "auth_token"

# Direct value
And I store the value "https://api.example.com" into global variable "api_base_url"

Using Global Variables

Global variables use the same {{variable_name}} syntax:

Scenario: Access protected resource
  Given I prepare a request for the "protected_data" endpoint
  And I set the request header "Authorization" to "Bearer {{auth_token}}"
  When I send the request

Variable Scope Comparison

TypeScopePersistence
Scenario VariableSingle scenarioCleared after scenario
Global VariableAll scenariosPersists until test suite ends

File Organization

features/
├── hooks/
│   ├── before_all.feature    # @BeforeAll
│   └── after_all.feature     # @AfterAll
├── auth/
│   └── login.feature
├── users/
│   └── user_crud.feature
└── products/
    └── product_tests.feature

Execution Order

  1. @BeforeAll scenarios execute (in order defined)
  2. All test scenarios execute
  3. @AfterAll scenarios execute (in order defined)

Real-World Examples

Authentication Setup

@BeforeAll
Feature: Authentication Setup

  Scenario: Login as admin user
    Given I prepare a request for the "login" endpoint
    And I set the request body to:
      """
      {
        "email": "admin@example.com",
        "password": "adminpass"
      }
      """
    When I send the request
    And I save the response path "$.accessToken" as global variable "admin_token"
    And I save the response path "$.refreshToken" as global variable "refresh_token"
    Then the response status code should be 200

  Scenario: Login as regular user
    Given I prepare a request for the "login" endpoint
    And I set the request body to:
      """
      {
        "email": "user@example.com",
        "password": "userpass"
      }
      """
    When I send the request
    And I save the response path "$.accessToken" as global variable "user_token"
    Then the response status code should be 200

Test Data Seeding

@BeforeAll
Feature: Seed Test Data

  Scenario: Create test products
    Given I prepare a request for the "create_product" endpoint
    And I set the request header "Authorization" to "Bearer {{admin_token}}"
    And I set the request body to:
      """
      {
        "name": "Test Product A",
        "price": 99.99
      }
      """
    When I send the request
    And I save the response path "$.data.id" as global variable "product_a_id"
    Then the response status code should be 201

    Given I prepare a request for the "create_product" endpoint
    And I set the request header "Authorization" to "Bearer {{admin_token}}"
    And I set the request body to:
      """
      {
        "name": "Test Product B",
        "price": 149.99
      }
      """
    When I send the request
    And I save the response path "$.data.id" as global variable "product_b_id"
    Then the response status code should be 201

Cleanup After Tests

@AfterAll
Feature: Cleanup Test Data

  Scenario: Remove test products
    Given I prepare a request for the "delete_product" endpoint
    And I set the following path parameters:
      | id | {{product_a_id}} |
    And I set the request header "Authorization" to "Bearer {{admin_token}}"
    When I send the request
    Then the response status code should be 204

    Given I prepare a request for the "delete_product" endpoint
    And I set the following path parameters:
      | id | {{product_b_id}} |
    And I set the request header "Authorization" to "Bearer {{admin_token}}"
    When I send the request
    Then the response status code should be 204

Best Practices

1. Keep Hooks Focused

Each hook scenario should have a single responsibility:

# Good: Focused scenarios
Scenario: Authenticate admin user
  # Only authentication steps

Scenario: Create test users
  # Only user creation steps

# Bad: Mixed responsibilities
Scenario: Setup everything
  # Authentication + Data creation + Configuration

2. Handle Failures Gracefully

If a BeforeAll hook fails, no tests will run. Design hooks to be resilient:

Scenario: Create test user if not exists
  Given I prepare a request for the "get_user_by_email" endpoint
  And I set the following query parameters:
    | email | test@example.com |
  When I send the request
  # Continue based on response...

3. Clean Up Completely

Ensure AfterAll hooks clean up all created data:

@AfterAll
Feature: Complete Cleanup

  Scenario: Remove all test data
    # Delete in reverse order of creation
    # Handle missing resources gracefully

4. Document Dependencies

Comment on what global variables are set and required:

@BeforeAll
Feature: Setup
  # Sets: auth_token, admin_token, test_user_id
  # Required by: All authenticated test scenarios

Troubleshooting

Hook Not Executing

  • Verify the @BeforeAll or @AfterAll tag is present
  • Check the feature file is in the features directory
  • Ensure the file has .feature extension

Global Variable Not Available

  • Confirm the variable was set in a BeforeAll hook
  • Check for typos in variable names
  • Verify BeforeAll completed successfully

Cleanup Not Running

  • AfterAll runs even if tests fail
  • Check for syntax errors in AfterAll feature
  • Review test output for hook execution status

Next Steps