From 0e9e390aa3fd74eb411d3b96128c0e8cadeefa1f Mon Sep 17 00:00:00 2001 From: Louis Deconinck Date: Thu, 17 Sep 2026 21:30:31 +0200 Subject: [PATCH] Document and test flaky(reruns=0) opting a test out of reruns The marker already takes priority over the global --reruns setting, so @pytest.mark.flaky(reruns=0) disables reruns for one test. Add regression tests pinning this behavior (including the --force-reruns and --reruns-mode=append caveats) and document it. Closes #187. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- README.rst | 14 ++++++++++++ changes/187.doc.rst | 3 +++ tests/test_pytest_rerunfailures.py | 36 ++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 changes/187.doc.rst diff --git a/README.rst b/README.rst index 747072ee..ba4d61d2 100644 --- a/README.rst +++ b/README.rst @@ -192,6 +192,20 @@ test to run: import random assert random.choice([True, False]) +To disable re-runs for a single test while keeping global re-runs enabled, +use ``reruns=0``. Since the marker takes priority over the global setting, +this test will not be re-run even when ``--reruns`` is passed: + +.. code-block:: python + + @pytest.mark.flaky(reruns=0) + def test_example(): + assert foo() == bar() + +Note that ``--force-reruns`` still overrides the marker, and with +``--reruns-mode=append`` the marker count is added to the global count, so +``reruns=0`` does not opt the test out in that mode. + Note that when teardown fails, two reports are generated for the case, one for the test case and the other for the teardown error. diff --git a/changes/187.doc.rst b/changes/187.doc.rst new file mode 100644 index 00000000..1a38eb33 --- /dev/null +++ b/changes/187.doc.rst @@ -0,0 +1,3 @@ +Document that ``@pytest.mark.flaky(reruns=0)`` disables re-runs for a single +test even when ``--reruns`` is set globally (the marker takes priority over +the global setting). diff --git a/tests/test_pytest_rerunfailures.py b/tests/test_pytest_rerunfailures.py index a4208c50..f054472b 100644 --- a/tests/test_pytest_rerunfailures.py +++ b/tests/test_pytest_rerunfailures.py @@ -548,6 +548,42 @@ def test_pass(): assert_outcomes(result, passed=1, rerun=2) +def test_flaky_marker_with_zero_reruns_disables_rerun(testdir): + testdir.makepyfile( + f""" + import pytest + @pytest.mark.flaky(reruns=0) + def test_fail(): + {temporary_failure()}""" + ) + result = testdir.runpytest("--reruns", "5") + assert_outcomes(result, passed=0, failed=1, rerun=0) + + +def test_flaky_marker_with_zero_reruns_append_mode_still_reruns(testdir): + testdir.makepyfile( + f""" + import pytest + @pytest.mark.flaky(reruns=0) + def test_fail(): + {temporary_failure()}""" + ) + result = testdir.runpytest("--reruns", "1", "--reruns-mode", "append") + assert_outcomes(result, passed=1, rerun=1) + + +def test_flaky_marker_with_zero_reruns_does_not_disable_force_reruns(testdir): + testdir.makepyfile( + f""" + import pytest + @pytest.mark.flaky(reruns=0) + def test_fail(): + {temporary_failure()}""" + ) + result = testdir.runpytest("--force-reruns", "1") + assert_outcomes(result, passed=1, rerun=1) + + def test_no_extra_test_summary_for_reruns_by_default(testdir): testdir.makepyfile( f"""