Skip to content

Commit ccad10a

Browse files
committed
skipping: fix dynamic xfail mark added in runtest not respected
If a test runtest phase (not setup) dynamically adds a pytest.mark.xfail mark to the item, it should be respected, but it wasn't. This regressed in 3e6fe92 (not released). Fix it by just always refreshing the mark if needed. This is mostly what was done before but in a more roundabout way.
1 parent 78f2dc0 commit ccad10a

File tree

2 files changed

+38
-7
lines changed

2 files changed

+38
-7
lines changed

src/_pytest/skipping.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,9 @@ def pytest_runtest_setup(item: Item) -> None:
236236
if skipped:
237237
skip(skipped.reason)
238238

239-
if not item.config.option.runxfail:
240-
item._store[xfailed_key] = xfailed = evaluate_xfail_marks(item)
241-
if xfailed and not xfailed.run:
242-
xfail("[NOTRUN] " + xfailed.reason)
239+
item._store[xfailed_key] = xfailed = evaluate_xfail_marks(item)
240+
if xfailed and not item.config.option.runxfail and not xfailed.run:
241+
xfail("[NOTRUN] " + xfailed.reason)
243242

244243

245244
@hookimpl(hookwrapper=True)
@@ -248,12 +247,16 @@ def pytest_runtest_call(item: Item) -> Generator[None, None, None]:
248247
if xfailed is None:
249248
item._store[xfailed_key] = xfailed = evaluate_xfail_marks(item)
250249

251-
if not item.config.option.runxfail:
252-
if xfailed and not xfailed.run:
253-
xfail("[NOTRUN] " + xfailed.reason)
250+
if xfailed and not item.config.option.runxfail and not xfailed.run:
251+
xfail("[NOTRUN] " + xfailed.reason)
254252

255253
yield
256254

255+
# The test run may have added an xfail mark dynamically.
256+
xfailed = item._store.get(xfailed_key, None)
257+
if xfailed is None:
258+
item._store[xfailed_key] = xfailed = evaluate_xfail_marks(item)
259+
257260

258261
@hookimpl(hookwrapper=True)
259262
def pytest_runtest_makereport(item: Item, call: CallInfo[None]):

testing/test_skipping.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import sys
22

33
import pytest
4+
from _pytest.pytester import Testdir
45
from _pytest.runner import runtestprotocol
56
from _pytest.skipping import evaluate_skip_marks
67
from _pytest.skipping import evaluate_xfail_marks
@@ -425,6 +426,33 @@ def test_this2(arg):
425426
result = testdir.runpytest(p)
426427
result.stdout.fnmatch_lines(["*1 xfailed*"])
427428

429+
def test_dynamic_xfail_set_during_runtest_failed(self, testdir: Testdir) -> None:
430+
# Issue #7486.
431+
p = testdir.makepyfile(
432+
"""
433+
import pytest
434+
def test_this(request):
435+
request.node.add_marker(pytest.mark.xfail(reason="xfail"))
436+
assert 0
437+
"""
438+
)
439+
result = testdir.runpytest(p)
440+
result.assert_outcomes(xfailed=1)
441+
442+
def test_dynamic_xfail_set_during_runtest_passed_strict(
443+
self, testdir: Testdir
444+
) -> None:
445+
# Issue #7486.
446+
p = testdir.makepyfile(
447+
"""
448+
import pytest
449+
def test_this(request):
450+
request.node.add_marker(pytest.mark.xfail(reason="xfail", strict=True))
451+
"""
452+
)
453+
result = testdir.runpytest(p)
454+
result.assert_outcomes(failed=1)
455+
428456
@pytest.mark.parametrize(
429457
"expected, actual, matchline",
430458
[

0 commit comments

Comments
 (0)