Parallel Execution

BehaveX manages concurrent Behave instances across multiple processes. You can run tests in parallel by feature or by scenario. When using the scenario scheme, examples within a scenario outline are also parallelized.

Parallel Test Executions

Basic Usage

behavex --parallel-processes=3
behavex -t=@TAG --parallel-processes=3
behavex -t=@TAG --parallel-processes=2 --parallel-scheme=scenario
behavex -t=@TAG --parallel-processes=5 --parallel-scheme=feature
behavex -t=@TAG --parallel-processes=5 --parallel-scheme=feature --show-progress-bar

Worker ID

BehaveX injects the worker_id variable into each Behave process context. With --parallel-processes 2, the first instance receives worker_id=0 and the second receives worker_id=1.

Access it in step definitions or hooks:

context.config.userdata['worker_id']

Hooks in Parallel Execution

Hook Firing Matrix

Hook

Sequential

--parallel-scheme feature

--parallel-scheme scenario

before_all_workers

Once — coordinator

Once — coordinator

Once — coordinator

before_all

Once

Once per worker

Once per worker

before_feature

Once per feature

Once per feature ✓

Once per scenario ⚠

before_scenario

Once per scenario

Once per scenario

Once per scenario

after_scenario

Once per scenario

Once per scenario

Once per scenario

after_feature

Once per feature

Once per feature ✓

Once per scenario ⚠

after_all

Once

Once per worker

Once per worker

after_all_workers

Once — coordinator

Once — coordinator

Once — coordinator

⚠ scenario scheme: Each worker process runs a single scenario. As a result, before_feature and after_feature fire once per scenario — the same frequency as before_scenario / after_scenario.

BehaveX-Specific Hooks

BehaveX adds before_all_workers and after_all_workers, which run once in the coordinator process — before any worker starts and after all workers finish. They are the right place for global setup/teardown that must not repeat across workers.

def before_all_workers(context):
    # Values set here are injected into every worker's context before before_all fires.
    context.base_url = "https://staging.example.com"
    context.db_name = "test_db"
    context.retry_count = 3

def after_all_workers(context):
    print(f"All workers finished. Base URL was: {context.base_url}")

Important: Values set on context in before_all_workers must be JSON-serializable (str, int, float, bool, list, dict, or None). Non-serializable values (e.g., database connections, sockets) raise a TypeError immediately.

Execution Metadata: context.behavex

BehaveX injects a context.behavex namespace in every worker process, available from before_all onwards:

Attribute

Type

Description

context.behavex.parallel_scheme

str

'scenario' or 'feature'

context.behavex.parallel_processes

int

Number of parallel workers configured

context.behavex.is_worker

bool

True when running inside a worker subprocess

context.behavex.worker_id

int

Worker index (0 in single-process mode)

Guard feature-level setup in scenario-parallel mode:

def before_feature(context, feature):
    if context.behavex.parallel_scheme == 'scenario':
        return  # fires once per scenario here — move setup to before_scenario
    setup_feature_database(feature.name)

def after_feature(context, feature):
    if context.behavex.parallel_scheme == 'scenario':
        return
    teardown_feature_database(feature.name)

Allocate resources per worker:

def before_all(context):
    if context.behavex.is_worker:
        context.browser = create_browser(worker_id=context.behavex.worker_id)

def after_all(context):
    if context.behavex.is_worker:
        context.browser.quit()

Test Execution Ordering

BehaveX lets you control the execution order of scenarios and features in parallel runs using special order tags.

Use Cases

  • Setup/teardown: Ensure setup scenarios run first and cleanup runs last

  • Data dependencies: Run data-creation tests before tests that consume that data

  • Smoke testing: Prioritize critical smoke tests

  • Parallel optimization: Run slower scenarios first to maximize worker utilization

Order Tags

Add @ORDER_NNN tags to your scenarios or features:

@ORDER_001
Scenario: Run first
    Given I perform initial setup

@ORDER_010
Scenario: Run second
    Given the initial setup is complete

@ORDER_100
Scenario: Run last
    Given all previous tests have completed

Rules:

  • Lower numbers execute first (@ORDER_001 before @ORDER_010)

  • Scenarios without order tags get default order 9999

  • Use zero-padded numbers for clarity (001, 010, 100)

  • Ordering only works with --parallel-processes > 1

Regular vs Strict Ordering

Regular Ordering (--order-tests)

Tests are sorted by order tags but can run simultaneously if parallel processes are available.

behavex --order-tests --parallel-processes=4 -t=@SMOKE
  • Faster: all processes run concurrently

  • Best for: performance optimization, general prioritization

Strict Ordering (--order-tests-strict)

Tests wait for all lower-order tests to complete before starting.

behavex --order-tests-strict --parallel-processes=3 -t=@INTEGRATION
  • Slower but guaranteed: @ORDER_002 won’t start until all @ORDER_001 tests finish

  • Best for: setup/teardown sequences, strict data dependencies

  • --order-tests-strict automatically enables --order-tests

Performance comparison:

Scenario: 6 tests tagged ORDER_001, ORDER_002, ORDER_003 with 3 parallel processes

Regular ordering (--order-tests):
  Time 0: ORDER_001, ORDER_002, ORDER_003 all start simultaneously
  Total time: ~1 minute

Strict ordering (--order-tests-strict):
  Time 0: Only ORDER_001 tests start
  Time 1: ORDER_001 finishes → ORDER_002 starts
  Time 2: ORDER_002 finishes → ORDER_003 starts
  Total time: ~3 minutes

Custom Order Prefix

behavex --order-tests --order-tag-prefix=PRIORITY --parallel-processes=3
@PRIORITY_001
Scenario: High priority scenario

@PRIORITY_050
Scenario: Medium priority scenario

@PRIORITY_100
Scenario: Low priority scenario

Feature-Level Ordering

When using --parallel-scheme=feature, place order tags on the feature itself:

@ORDER_001
Feature: Database Setup
    Scenario: Create schema
    Scenario: Insert initial data

@ORDER_002
Feature: Application Tests
    Scenario: Test user login

Feature: Unordered Feature
    # No ORDER tag — gets default order 9999