From 2c41416092375f9a8b61922b4cdba1772ddcf23f Mon Sep 17 00:00:00 2001 From: Louis Deconinck Date: Thu, 10 Sep 2026 21:13:51 +0200 Subject: [PATCH] Preserve rerun status for teardown failures --- changes/366.bugfix.rst | 1 + src/pytest_rerunfailures.py | 2 ++ tests/test_pytest_rerunfailures.py | 26 +++++++++++++++++++++++--- 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 changes/366.bugfix.rst diff --git a/changes/366.bugfix.rst b/changes/366.bugfix.rst new file mode 100644 index 0000000..1b0d614 --- /dev/null +++ b/changes/366.bugfix.rst @@ -0,0 +1 @@ +Mark teardown failures from an attempt that is rerun as reruns, so a later successful attempt is not reported as an error. diff --git a/src/pytest_rerunfailures.py b/src/pytest_rerunfailures.py index 627287f..d1bd8a6 100644 --- a/src/pytest_rerunfailures.py +++ b/src/pytest_rerunfailures.py @@ -1223,6 +1223,8 @@ def pytest_runtest_protocol(item, nextitem): for report in reports: # 3 reports: setup, call, teardown report.rerun = item.execution_count - 1 if rerun_triggered: + if report.failed: + report.outcome = "rerun" item.ihook.pytest_runtest_logreport(report=report) elif ( condition diff --git a/tests/test_pytest_rerunfailures.py b/tests/test_pytest_rerunfailures.py index 67122fa..9b1d42d 100644 --- a/tests/test_pytest_rerunfailures.py +++ b/tests/test_pytest_rerunfailures.py @@ -1012,10 +1012,30 @@ def pytest_sessionfinish(): stdout = result.stdout.str() assert "ATTEMPTS: 2" in stdout - assert ( - "FIRST ATTEMPT REPORTS: [('call', 'rerun'), ('teardown', 'failed')]" in stdout + assert "FIRST ATTEMPT REPORTS: [('call', 'rerun'), ('teardown', 'rerun')]" in stdout + + +def test_call_and_teardown_failures_are_rerun_together(testdir): + testdir.makepyfile( + """ + import pytest + + @pytest.fixture + def demo_fixture(request): + yield + if request.node.execution_count == 1: + raise RuntimeError("teardown failure") + + def test_demo(demo_fixture, request): + if request.node.execution_count == 1: + pytest.fail("call failure") + """ ) + result = testdir.runpytest("--reruns", "1") + + assert_outcomes(result, passed=1, rerun=2, failed=0, error=0) + def test_pytest_runtest_logfinish_is_called(testdir): hook_message = "Message from pytest_runtest_logfinish hook" @@ -1959,7 +1979,7 @@ def test_fail(broken_fixture): ) result = testdir.runpytest("-s") - assert_outcomes(result, passed=0, failed=1, error=3, rerun=2) + assert_outcomes(result, passed=0, failed=1, error=1, rerun=4) assert result.stdout.str().count("module teardown") == 1