Priority-based execution for Behave BDD
Project description
behave-priority
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 prioritypriority_tag="smoke"— executes scenarios with that tag first, then the restreverse=True— executes lowest priority first (useful for debugging)
Fail-fast
stop_after_failures=N— stops execution after N failed scenariosstop_on_critical=True— stops if any@criticalscenario 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:
- Set the
BEHAVE_PRIORITY_COORD_DIRenvironment variable to a shared directory path - Pass
parallel_coord=Truetosetup_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 timingreport_format="text"(default) — human-readable table with summaryreport_format="json"— machine-readable JSON with entries and summaryreport_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_savedestimation 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 triggeredafter_scenario_hook(context, scenario)— records result, checks fail-fastpriority_report(context)— prints execution report inafter_allcleanup_parallel_coord(context)— removes worker file from coordination directory inafter_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 listparse_feature_priority(tags) -> int | None— parse@feature-priority(N)from a tag listresolve_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 errorsPriorityParseError— 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
before_all:setup_priority()reads config, sorts features and scenarios by prioritybefore_scenario: hook skips scenario if fail-fast was triggeredafter_scenario: hook records result, checks fail-fast conditionsafter_all:priority_report()prints execution report if enabled
Use cases
- CI critical-first: Run
@priority(1)scenarios first. If any fail, stop immediately. Don't waste 20 minutes on regression. - Smoke tests: Tag smoke tests
@priority(1) @critical, run withstop_on_critical=True. Get smoke results in 30 seconds. - Time-limited runs: In PR pipelines with time budget,
order=Trueensures most important tests run first. - Debugging:
reverse=Trueruns 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. Withparallel_coord=TrueandBEHAVE_PRIORITY_COORD_DIRset, failure counts are aggregated globally across all workers. See Parallel coordination. - Critical stop (
stop_on_critical): By default per-worker only. Withparallel_coord=True, a critical failure in any worker triggers stop in all workers. - Counters:
failed_count,executed_count,critical_failed, andshould_stopare 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_savedestimation: 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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
468f8e075b7233f5eeabd63660f4a36f1f13406a43c63d45252a590095001159
|
|
| MD5 |
521684c47f5c9e04e075e36b43e9c076
|
|
| BLAKE2b-256 |
eaaaf33b471dcb0ec906e3248b417b1c7f25c0196b91ce5d4c488f7cd368f017
|
Provenance
The following attestation bundles were made for behave_priority-1.0.0.tar.gz:
Publisher:
release.yml on MathiasPaulenko/behave-priority
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
behave_priority-1.0.0.tar.gz -
Subject digest:
468f8e075b7233f5eeabd63660f4a36f1f13406a43c63d45252a590095001159 - Sigstore transparency entry: 2167184619
- Sigstore integration time:
-
Permalink:
MathiasPaulenko/behave-priority@b0b46ba1e95c9ecddb6091e057676cac25749a25 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/MathiasPaulenko
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b0b46ba1e95c9ecddb6091e057676cac25749a25 -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a444ec954adb7c50108ddb42207470f756b60c3fed1ab3467300fddc880327fa
|
|
| MD5 |
c9bf83e0e34da51b00d60a2f2a4d4205
|
|
| BLAKE2b-256 |
0738d8002d8fa54a7b593cef6e49d565416f719497ff365f0afac10686d456f3
|
Provenance
The following attestation bundles were made for behave_priority-1.0.0-py3-none-any.whl:
Publisher:
release.yml on MathiasPaulenko/behave-priority
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
behave_priority-1.0.0-py3-none-any.whl -
Subject digest:
a444ec954adb7c50108ddb42207470f756b60c3fed1ab3467300fddc880327fa - Sigstore transparency entry: 2167184630
- Sigstore integration time:
-
Permalink:
MathiasPaulenko/behave-priority@b0b46ba1e95c9ecddb6091e057676cac25749a25 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/MathiasPaulenko
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b0b46ba1e95c9ecddb6091e057676cac25749a25 -
Trigger Event:
push
-
Statement type: