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
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)
| File | Size | Uploaded | |
|---|---|---|---|
| behave_priority-1.0.1.tar.gz | 49.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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