From 4407154810437e4a3739d4d576698d423a17b2fb Mon Sep 17 00:00:00 2001 From: Shlomi Amit Date: Sun, 25 Feb 2024 13:54:47 +0200 Subject: [PATCH 1/5] Fix tests reported as failures when rerun happened due to exception raised from fixture teardown when using only_rerun --- CHANGES.rst | 6 ++++++ src/pytest_rerunfailures.py | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 9d1db7b..46c9d3f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,12 @@ Breaking changes - Drop support for Python 3.7. +Bug fixes ++++++++++ + +- Fix tests reported as failures when rerun happened due to exception raised from fixture teardown when using only_rerun. + (`#261 `_) + 13.0 (2023-11-22) ----------------- diff --git a/src/pytest_rerunfailures.py b/src/pytest_rerunfailures.py index 211b7e9..7433206 100644 --- a/src/pytest_rerunfailures.py +++ b/src/pytest_rerunfailures.py @@ -534,9 +534,17 @@ def pytest_runtest_protocol(item, nextitem): item.ihook.pytest_runtest_logstart(nodeid=item.nodeid, location=item.location) reports = runtestprotocol(item, nextitem=nextitem, log=False) + # Check all reports to see if any rerun is needed (So teardown report is checked before processing call (test)) + should_rerun = False + for r in reports: + r.rerun = item.execution_count - 1 + should_rerun = not _should_not_rerun(item, r, reruns) + if should_rerun: + break + + for report in reports: # 3 reports: setup, call, teardown - report.rerun = item.execution_count - 1 - if _should_not_rerun(item, report, reruns): + if not should_rerun: # last run or no failure detected, log normally item.ihook.pytest_runtest_logreport(report=report) else: From bdb94849b9726dc45c7fe747a5b0805f610639fd Mon Sep 17 00:00:00 2001 From: Shlomi Amit Date: Mon, 26 Feb 2024 15:30:16 +0200 Subject: [PATCH 2/5] pre-commit --- src/pytest_rerunfailures.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pytest_rerunfailures.py b/src/pytest_rerunfailures.py index 7433206..240782c 100644 --- a/src/pytest_rerunfailures.py +++ b/src/pytest_rerunfailures.py @@ -534,7 +534,8 @@ def pytest_runtest_protocol(item, nextitem): item.ihook.pytest_runtest_logstart(nodeid=item.nodeid, location=item.location) reports = runtestprotocol(item, nextitem=nextitem, log=False) - # Check all reports to see if any rerun is needed (So teardown report is checked before processing call (test)) + # Check all reports to see if any rerun is needed + # (So teardown report is checked before processing call (test)) should_rerun = False for r in reports: r.rerun = item.execution_count - 1 @@ -542,7 +543,6 @@ def pytest_runtest_protocol(item, nextitem): if should_rerun: break - for report in reports: # 3 reports: setup, call, teardown if not should_rerun: # last run or no failure detected, log normally From 2409ecfd2fb2f04d5cefad917851dd769033e7bc Mon Sep 17 00:00:00 2001 From: Shlomi Amit Date: Mon, 26 Feb 2024 15:50:29 +0200 Subject: [PATCH 3/5] fix test_execution_count_exposed wrong test assertion after bug fix --- tests/test_pytest_rerunfailures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_pytest_rerunfailures.py b/tests/test_pytest_rerunfailures.py index c4f7623..c174ca7 100644 --- a/tests/test_pytest_rerunfailures.py +++ b/tests/test_pytest_rerunfailures.py @@ -472,7 +472,7 @@ def pytest_runtest_teardown(item): assert item.execution_count == 3""" ) result = testdir.runpytest("--reruns", "2") - assert_outcomes(result, passed=3, rerun=2) + assert_outcomes(result, passed=1, rerun=2) def test_rerun_report(testdir): From 6937bc1ed4f55aabbf72e0c666d7f9a77379ca4b Mon Sep 17 00:00:00 2001 From: Shlomi Amit Date: Wed, 6 Mar 2024 17:33:21 +0200 Subject: [PATCH 4/5] check for all reports for rerun_except --- src/pytest_rerunfailures.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/pytest_rerunfailures.py b/src/pytest_rerunfailures.py index 21a08a7..088ea8c 100644 --- a/src/pytest_rerunfailures.py +++ b/src/pytest_rerunfailures.py @@ -550,15 +550,22 @@ def pytest_runtest_protocol(item, nextitem): # Check all reports to see if any rerun is needed # (So teardown report is checked before processing call (test)) - should_rerun = False + except_found = False for r in reports: - r.rerun = item.execution_count - 1 - should_rerun = not _should_not_rerun(item, r, reruns) - if should_rerun: + rerun_except_errors = _get_rerun_filter_regex(item, "rerun_except") + except_found = rerun_except_errors and _matches_any_rerun_except_error( + rerun_except_errors, r + ) + if except_found: break + should_not_rerun = True + for r in reports: + r.rerun = item.execution_count - 1 + should_not_rerun = _should_not_rerun(item, r, reruns) or except_found + for report in reports: # 3 reports: setup, call, teardown - if not should_rerun: + if should_not_rerun: # last run or no failure detected, log normally item.ihook.pytest_runtest_logreport(report=report) else: From 13eb22d5fd32b16db5a5700cd209e2c6de3ef621 Mon Sep 17 00:00:00 2001 From: Shlomi Amit Date: Thu, 7 Mar 2024 11:12:43 +0200 Subject: [PATCH 5/5] fix test failures and for consistency --- src/pytest_rerunfailures.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/pytest_rerunfailures.py b/src/pytest_rerunfailures.py index 088ea8c..148abf0 100644 --- a/src/pytest_rerunfailures.py +++ b/src/pytest_rerunfailures.py @@ -551,18 +551,23 @@ def pytest_runtest_protocol(item, nextitem): # Check all reports to see if any rerun is needed # (So teardown report is checked before processing call (test)) except_found = False - for r in reports: + for report in reports: rerun_except_errors = _get_rerun_filter_regex(item, "rerun_except") except_found = rerun_except_errors and _matches_any_rerun_except_error( - rerun_except_errors, r + rerun_except_errors, report ) if except_found: + # One of the reports has rerun_except error match, + # no need to scan the other reports break should_not_rerun = True - for r in reports: - r.rerun = item.execution_count - 1 - should_not_rerun = _should_not_rerun(item, r, reruns) or except_found + for report in reports: + report.rerun = item.execution_count - 1 + should_not_rerun = _should_not_rerun(item, report, reruns) or except_found + if not should_not_rerun: + # One of the reports should rerun, no need to scan the other reports + break for report in reports: # 3 reports: setup, call, teardown if should_not_rerun: