Skip to main content

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

Release files for behave-priority 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for behave-priority 1.0.1
File Size Uploaded
behave_priority-1.0.1.tar.gz 49.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for behave-priority 1.0.1
File Interpreter ABI Platform
behave_priority-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 70.5 kB

Release files / behave_priority-1.0.1.tar.gz

Download URL behave_priority-1.0.1.tar.gz
Size 49.5 kB
Tags Source
SHA-256 checksum
How to use checksums
e5baf46b7ba963ade39bf37c715d76db9a6674707f3c9664bac47e5da6e82503
BLAKE2b-256 checksum
How to use checksums
caea6294793e4ebe62187f461436acce9e99944b4d4abb0f3812aaf4863cb27e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 6, 2026.

Transparency log

Release files / behave_priority-1.0.1-py3-none-any.whl

Download URL behave_priority-1.0.1-py3-none-any.whl
Size 21.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
511c078b2e36dcfe33c1a64f8f0f7eb13d75d55dd2f3a824815ad2eb1ea95ef8
BLAKE2b-256 checksum
How to use checksums
4783357cbd46bb4de05c5dbd0ebfcd2d2ff5e0380f54987fc33d3660c4d2533a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 6, 2026.

Transparency log

Release history Release notifications | RSS feed

1.1.0

2 release files

This release

1.0.1 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page