Skip to main content

Priority-based execution for Behave BDD

Project description

behave-priority

Python 3.11+ License: MIT Tests Coverage mypy: strict ruff

Priority-based execution for Behave BDD. Execute scenarios ordered by priority, with fail-fast and smoke-first support.

Problem

Behave executes scenarios in file order. There is no way to:

  • Run critical tests first
  • Stop after N failures (intelligent fail-fast)
  • Run smoke tests before regression
  • Guarantee coverage when time is limited

In CI, if critical tests fail, you waste time waiting for the full regression suite to finish.

Solution

behave-priority reorders scenario execution by priority tags and provides fail-fast controls — all configured programmatically in environment.py, no CLI flags needed.

Features

Priority tags

  • @priority(1) tag on scenarios — lower number = higher priority
  • @feature-priority(1) at feature level — applies to all scenarios in the feature
  • Scenario-level @priority(N) overrides feature-level priority
  • Scenarios without priority tag default to lowest priority (executed last)

Execution ordering

  • order=True — executes scenarios from highest to lowest priority
  • priority_tag="smoke" — executes scenarios with that tag first, then the rest
  • reverse=True — executes lowest priority first (useful for debugging)

Fail-fast

  • stop_after_failures=N — stops execution after N failed scenarios
  • stop_on_critical=True — stops if any @critical scenario fails
  • Combines with order=True: run critical first, stop if they fail, skip regression

Parallel coordination

When running with behave --parallel=N, each worker is a separate process. By default, fail-fast is per-worker only. To coordinate fail-fast across all workers:

  1. Set the BEHAVE_PRIORITY_COORD_DIR environment variable to a shared directory path
  2. Pass parallel_coord=True to setup_priority
export BEHAVE_PRIORITY_COORD_DIR=/tmp/behave_priority_coord
behave --parallel=4
setup_priority(
    context,
    order=True,
    stop_after_failures=3,
    parallel_coord=True,
)

Each worker writes its failure state to a JSON file in the coordination directory. stop_after_failures and stop_on_critical are evaluated globally across all workers. Call cleanup_parallel_coord(context) in after_all to remove the worker's file.

Reporting

  • report=True — prints execution order with priorities and timing
  • report_format="text" (default) — human-readable table with summary
  • report_format="json" — machine-readable JSON with entries and summary
  • report_format="csv" — CSV with one row per scenario entry
  • Shows: scenario name, priority value, status (passed/failed/skipped), duration
  • Summary: how many critical passed, how many failed, total time saved by fail-fast
  • time_saved estimation uses priority-bucketed averages (scenarios grouped by priority range 0-99, 100-199, etc.)

Example with JSON output for CI/CD integration:

setup_priority(
    context,
    order=True,
    report=True,
    report_format="json",
)

Installation

pip install behave-priority

For development:

pip install -e ".[dev]"

Quick start

In your features/environment.py:

from behave_priority import (
    setup_priority,
    before_scenario_hook,
    after_scenario_hook,
    priority_report,
)

def before_all(context):
    setup_priority(
        context,
        order=True,
        stop_after_failures=3,
        stop_on_critical=True,
        report=True,
    )

def before_scenario(context, scenario):
    before_scenario_hook(context, scenario)

def after_scenario(context, scenario):
    after_scenario_hook(context, scenario)

def after_all(context):
    priority_report(context)

In your .feature files:

Feature: User authentication

  @priority(1)
  @critical
  Scenario: Login with valid credentials
    Given a registered user
    When the user logs in
    Then the user should be authenticated

  @priority(2)
  Scenario: Login with invalid password
    Given a registered user
    When the user logs in with wrong password
    Then the login should fail

  @priority(5)
  Scenario: Remember me checkbox
    Given a registered user
    When the user checks remember me
    Then the session should persist

API reference

setup_priority(context, **kwargs)

Configures priority execution in before_all. All parameters are optional.

Parameter Type Default Description
order bool False Sort scenarios by priority
reverse bool False Reverse sort order (lowest priority first)
priority_tag str | None None Tag name to run first (e.g. "smoke")
stop_after_failures int | None None Stop after N failures
stop_on_critical bool False Stop if any @critical scenario fails
critical_tag str "critical" Tag name for critical scenarios
default_priority int 999 Priority for untagged scenarios
report bool False Print execution report after run
report_format "text" | "json" | "csv" "text" Output format for the report
parallel_coord bool False Enable cross-process fail-fast via BEHAVE_PRIORITY_COORD_DIR

Hook functions

  • before_scenario_hook(context, scenario) — skips scenario if fail-fast triggered
  • after_scenario_hook(context, scenario) — records result, checks fail-fast
  • priority_report(context) — prints execution report in after_all
  • cleanup_parallel_coord(context) — removes worker file from coordination directory in after_all

PriorityConfig

Immutable frozen dataclass with all configuration options. Can be constructed directly for advanced use cases.

Parser functions

  • parse_priority(tags) -> int | None — parse @priority(N) from a tag list
  • parse_feature_priority(tags) -> int | None — parse @feature-priority(N) from a tag list
  • resolve_priority(scenario_tags, feature_tags, config, rule_tags=None) -> int — resolve effective priority (scenario > rule > feature > default)
  • is_critical(tags, critical_tag) -> bool — check if scenario is critical

Exceptions

  • PriorityError — base exception for all behave-priority errors
  • PriorityParseError — raised when a priority tag has invalid syntax

Architecture

behave_priority/
├── __init__.py          # Public exports
├── exceptions.py        # PriorityError, PriorityParseError
├── config.py            # PriorityConfig (frozen dataclass)
├── parser.py            # Tag priority parsing
├── sorter.py            # ScenarioSorter — reorders behave's runner
├── hooks.py             # setup_priority, hook functions, PriorityState
├── parallel.py          # ParallelCoordinator — cross-process fail-fast
└── report.py            # PriorityReport, ReportEntry, ReportSummary

How it works

  1. before_all: setup_priority() reads config, sorts features and scenarios by priority
  2. before_scenario: hook skips scenario if fail-fast was triggered
  3. after_scenario: hook records result, checks fail-fast conditions
  4. after_all: priority_report() prints execution report if enabled

Use cases

  1. CI critical-first: Run @priority(1) scenarios first. If any fail, stop immediately. Don't waste 20 minutes on regression.
  2. Smoke tests: Tag smoke tests @priority(1) @critical, run with stop_on_critical=True. Get smoke results in 30 seconds.
  3. Time-limited runs: In PR pipelines with time budget, order=True ensures most important tests run first.
  4. Debugging: reverse=True runs obscure/edge-case tests first while you're fresh.

Requirements

  • Python >= 3.11
  • behave >= 1.2.6

Development

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest

# Lint
ruff check behave_priority/ tests/

# Type check
mypy --strict behave_priority/

# Coverage
pytest --cov=behave_priority --cov-report=term-missing

Limitations

Parallel execution (--parallel)

When behave runs with --parallel=N, each worker process gets its own isolated PriorityState. This has the following consequences:

  • Scenario reordering: Each worker sorts only its own subset of scenarios. Global priority ordering across workers is not guaranteed. A @priority(1) scenario assigned to worker 2 may run after a @priority(5) scenario in worker 1.
  • Fail-fast (stop_after_failures): By default, only stops scenarios within the same worker. With parallel_coord=True and BEHAVE_PRIORITY_COORD_DIR set, failure counts are aggregated globally across all workers. See Parallel coordination.
  • Critical stop (stop_on_critical): By default per-worker only. With parallel_coord=True, a critical failure in any worker triggers stop in all workers.
  • Counters: failed_count, executed_count, critical_failed, and should_stop are all per-process. The final report reflects only the worker that generated it.
  • Reports: Generated independently per worker. Each worker prints its own report covering only the scenarios it executed. There is no merged or aggregated report.
  • time_saved estimation: Inaccurate in parallel mode. The estimation assumes sequential execution; with N workers, skipped scenarios in one worker overlap with execution in others.
  • priority_tag: Scenarios matching the priority tag are sorted first within each worker, but not globally across workers.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

behave_priority-1.0.0.tar.gz (49.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

behave_priority-1.0.0-py3-none-any.whl (21.0 kB view details)

Uploaded Python 3

File details

Details for the file behave_priority-1.0.0.tar.gz.

File metadata

  • Download URL: behave_priority-1.0.0.tar.gz
  • Upload date:
  • Size: 49.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for behave_priority-1.0.0.tar.gz
Algorithm Hash digest
SHA256 468f8e075b7233f5eeabd63660f4a36f1f13406a43c63d45252a590095001159
MD5 521684c47f5c9e04e075e36b43e9c076
BLAKE2b-256 eaaaf33b471dcb0ec906e3248b417b1c7f25c0196b91ce5d4c488f7cd368f017

See more details on using hashes here.

Provenance

The following attestation bundles were made for behave_priority-1.0.0.tar.gz:

Publisher: release.yml on MathiasPaulenko/behave-priority

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file behave_priority-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: behave_priority-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 21.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for behave_priority-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a444ec954adb7c50108ddb42207470f756b60c3fed1ab3467300fddc880327fa
MD5 c9bf83e0e34da51b00d60a2f2a4d4205
BLAKE2b-256 0738d8002d8fa54a7b593cef6e49d565416f719497ff365f0afac10686d456f3

See more details on using hashes here.

Provenance

The following attestation bundles were made for behave_priority-1.0.0-py3-none-any.whl:

Publisher: release.yml on MathiasPaulenko/behave-priority

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page