Mark Specific Tests as Flaky
The @pytest.mark.flaky decorator allows you to mark individual tests as flaky and configure them to
automatically re-run a specified number of times upon failure. This is particularly useful for specific tests
that are intermittently failing due to non-deterministic conditions (e.g., network latency, race conditions).
That mark also allows to override global settings specified via command-line options.
Basic Usage
To use the @pytest.mark.flaky decorator, include it in your test function and specify the number of retries using the reruns argument:
@pytest.mark.flaky(reruns=3)
def test_example():
import random
assert random.choice([True, False])
In this example, test_example will automatically re-run up to 3 times if it fails.
Additional Options
The @pytest.mark.flaky decorator supports the following optional arguments:
reruns_delay
Specify a delay (in seconds) between re-runs.
@pytest.mark.flaky(reruns=5, reruns_delay=2)
def test_example():
import random
assert random.choice([True, False])
This will retry the test 5 times with a 2-second pause between attempts.
condition
Re-run the test only if a specified condition is met. The condition can be a boolean, a string to be evaluated, or a callable.
Boolean conditions are evaluated directly:
import sys
@pytest.mark.flaky(reruns=3, condition=sys.platform.startswith("win32"))
def test_example():
import random
assert random.choice([True, False])
In this example, the test will only be re-run if the operating system is Windows.
A callable condition that accepts one argument receives the exception that caused a failed test phase. Existing zero-argument callables remain supported. This allows a re-run decision to use exception attributes rather than only its type or message:
class TemporaryError(Exception):
def __init__(self, status):
self.status = status
@pytest.mark.flaky(
reruns=3,
condition=lambda error: error.status in {429, 503},
)
def test_service_request():
raise TemporaryError(429)
A string condition can inspect the same exception through the reserved
error name. Its evaluation context also contains os, sys,
platform, config (the pytest config object), and the test function’s
globals:
@pytest.mark.flaky(reruns=3, condition="error.status in {429, 503}")
def test_service_request():
raise TemporaryError(429)
When more than one test phase fails in an attempt, the test is re-run if the condition matches any of those failures. Each failure is evaluated at most once. If a callable or string condition raises an exception, pytest emits a warning and does not re-run for that failure.
only_rerun
Re-run the test only for specific exception types or patterns.
That overrides the --only-rerun command-line option and the
only_rerun ini setting.
@pytest.mark.flaky(reruns=5, only_rerun=["AssertionError", "ValueError"])
def test_example():
raise AssertionError()
rerun_except
Exclude specific exception types or patterns from triggering a re-run.
That overrides the --rerun-except command-line option and the
rerun_except ini setting.
@pytest.mark.flaky(reruns=5, rerun_except="AssertionError")
def test_example():
raise ValueError()