behave-retry
Automatic retry for failed Behave scenarios — real re-execution, tag overrides, exception filtering, and flakiness stats.
Why?
Behave has no built-in retry. When a scenario fails due to flakiness (timing, network, race conditions), there's no way to re-run it automatically. Cucumber has --retry natively. Behave doesn't.
behave-retry fills that gap by patching Behave's Scenario.run to re-execute failed scenarios automatically — with tag overrides, exception filtering, and flakiness stats.
Comparison
| Feature | behave-retry | Cucumber --retry |
pytest-rerunfailures |
|---|---|---|---|
| Per-scenario retry override | @retry:N tag |
@retry N tag |
@pytest.mark.flaky(reruns=N) |
| Exception filtering | retry_on=[...] |
No | reruns_exceptions |
| Tag filtering | retry_tags=["@flaky"] |
No | No |
| Global retry budget | max_total_retries |
No | No |
| Exponential backoff | retry_delay + backoff_factor |
No | reruns_delay (fixed) |
| On-retry callback | on_retry |
No | No |
| Retry stats | Human + JSON | No | No |
| Scenario Outline support | Per-example keys | N/A | N/A |
| Runtime dependencies | Zero | — | pytest plugin |
Install
pip install behave-retry
Quick start
# environment.py
from behave_retry import setup_retry, after_scenario_hook, retry_report
def before_all(context):
setup_retry(context, max_retries=3)
def after_scenario(context, scenario):
after_scenario_hook(context, scenario)
def after_all(context):
print(retry_report(context))
That's it. Failed scenarios will now be re-executed up to 3 times automatically.
Features
- Global retry — retry all failed scenarios up to N times
- Tag-filtered retry — only retry scenarios with specific tags (
@flaky) - Exception-filtered retry — only retry on specific exception types or string names
- Per-scenario override —
@retry:Ntag overrides global config - Feature-level tags —
@retry:Non Feature inherits to scenarios - Global retry budget — limit total retries across all scenarios
- Retry delay and backoff — configurable delay with exponential backoff
- On-retry callback — custom logic before each retry (cleanup, screenshots, etc.)
- Flakiness stats — human-readable summary and machine-readable JSON export
- Scenario Outline support — unique keys per example, independent retry counts
- Logging — via standard
loggingmodule underbehave_retrylogger - Type-safe —
py.typedmarker included, full type hints, mypy clean
Configuration
setup_retry(
context,
max_retries=3, # max retries per scenario
retry_tags=["@flaky"], # only retry tagged scenarios
retry_on=[AssertionError, TimeoutError], # only retry these exceptions
retry_delay=2.0, # 2s delay before first retry
backoff_factor=2.0, # double delay each retry (2s, 4s, 8s)
on_retry=lambda ctx, sc, att, exc: print(f"Retry {sc.name} #{att}: {exc}"),
max_total_retries=20, # stop after 20 total retries across all scenarios
)
See the configuration guide for full details.
How it works
setup_retrypatchesbehave.model.Scenario.runwith a retry-aware wrapper.- When a scenario fails, the wrapper checks:
- Does the scenario have retries remaining? (global
max_retriesor@retry:Noverride) - Is the scenario tagged for retry? (if
retry_tagsis set) - Is the exception type eligible? (if
retry_onis set) - Is the global retry budget exhausted? (if
max_total_retriesis set)
- Does the scenario have retries remaining? (global
- If all checks pass, it resets the scenario state and re-runs it.
- Stats are tracked and available via
retry_report()orstats.to_dict().
Documentation
| Section | Description |
|---|---|
| Installation | Install from PyPI or source |
| Quick start | Three-step setup guide |
| Features | Complete feature walkthrough with examples |
| Configuration | All parameters, validation, and precedence rules |
| Examples | Real-world recipes for common use cases |
| API reference | Full autodoc API |
| Changelog | Version history |
Contributing
Contributions are welcome! See CONTRIBUTING.md for guidelines.
License
MIT — Copyright (c) 2026 Mathias Paulenko
Release files for behave-retry 1.8.3
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_retry-1.8.3.tar.gz | 44.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| behave_retry-1.8.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 58.3 kB
Release files / behave_retry-1.8.3.tar.gz
| Download URL | behave_retry-1.8.3.tar.gz |
|---|---|
| Size | 44.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
281d91e44de8ab71a0bab3a0a68b1c1c749c188e97783ec4e1e3f5775acffbc2
|
|
BLAKE2b-256 checksum How to use checksums |
cff76f047e3ca3572cdd4578713a8aa9724bad3e4b9b5a8336cff63ca751f713
|
| 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_retry-1.8.3-py3-none-any.whl
| Download URL | behave_retry-1.8.3-py3-none-any.whl |
|---|---|
| Size | 13.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
63038034529a42fb25bad2ef51994f5fffe6ff578f953bb98a3371cf8a442c88
|
|
BLAKE2b-256 checksum How to use checksums |
ba8219824a8eb588ab112814ce3e101ff11057763ffe17d78221b1b23a4d2e79
|
| 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