From a97bf3d6b72ff19cc0c00a87772033da7668534c Mon Sep 17 00:00:00 2001 From: Casey Brooks Date: Thu, 25 Dec 2025 21:10:26 +0000 Subject: [PATCH 1/2] fix(skipping): guard xfail handling for runxfail --- src/_pytest/skipping.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 7bd975e5a09..a9ba93e57cd 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -270,13 +270,15 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]): else: rep.longrepr = "Unexpected success" rep.outcome = "failed" - elif item.config.option.runxfail: - pass # don't interfere - elif call.excinfo and isinstance(call.excinfo.value, xfail.Exception): + elif ( + not item.config.option.runxfail + and call.excinfo + and isinstance(call.excinfo.value, xfail.Exception) + ): assert call.excinfo.value.msg is not None rep.wasxfail = "reason: " + call.excinfo.value.msg rep.outcome = "skipped" - elif not rep.skipped and xfailed: + elif (not item.config.option.runxfail) and not rep.skipped and xfailed: if call.excinfo: raises = xfailed.raises if raises is not None and not isinstance(call.excinfo.value, raises): From 42af5091cd4f3b2d8e2de22cf1ec1f0a45121919 Mon Sep 17 00:00:00 2001 From: Casey Brooks Date: Thu, 25 Dec 2025 21:16:46 +0000 Subject: [PATCH 2/2] test(skipping): cover skip location under runxfail --- testing/test_skipping.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 0b1c0b49b03..57ada9928c5 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -619,6 +619,21 @@ def test_bar(): result = testdir.runpytest("-rs") result.stdout.fnmatch_lines(["*for lolz*", "*1 skipped*"]) + def test_skip_reports_item_location_with_runxfail(self, testdir): + testdir.makepyfile( + test_skip=""" + import pytest + + @pytest.mark.skip(reason="skip me") + def test_skip(): + pass + """ + ) + result = testdir.runpytest("-q", "-rs", "--runxfail") + result.stdout.fnmatch_lines(["*test_skip.py:*: skip me*"]) + result.stdout.no_fnmatch_line("*src/_pytest/skipping.py*") + assert result.ret == 0 + def test_only_skips_marked_test(self, testdir): testdir.makepyfile( """ @@ -679,6 +694,21 @@ def test_that(): result.stdout.fnmatch_lines(["*SKIP*1*test_foo.py*platform*", "*1 skipped*"]) assert result.ret == 0 + def test_skipif_reports_item_location_with_runxfail(self, testdir): + testdir.makepyfile( + test_skipif=""" + import pytest + + @pytest.mark.skipif(True, reason="conditional skip") + def test_skipif(): + pass + """ + ) + result = testdir.runpytest("-q", "-rs", "--runxfail") + result.stdout.fnmatch_lines(["*test_skipif.py:*: conditional skip*"]) + result.stdout.no_fnmatch_line("*src/_pytest/skipping.py*") + assert result.ret == 0 + def test_skipif_using_platform(self, testdir): item = testdir.getitem( """