Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/14090.improvement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improvement gathering the ``wasxfail`` value when the ``pytest.mark.xfail`` fixture is combined with explicit calls to ``pytest.fail`` or ``pytest.xfail``.
9 changes: 6 additions & 3 deletions src/_pytest/skipping.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,12 @@ def pytest_runtest_makereport(
xfailed = item.stash.get(xfailed_key, None)
if item.config.option.runxfail:
pass # don't interfere
elif call.excinfo and isinstance(call.excinfo.value, xfail.Exception):
assert call.excinfo.value.msg is not None
rep.wasxfail = call.excinfo.value.msg
elif call.excinfo and isinstance(
call.excinfo.value, (fail.Exception, xfail.Exception)
):
rep.wasxfail = getattr(call.excinfo.value, "msg", "")
if xfailed and xfailed.reason not in (None, ""):
rep.wasxfail = xfailed.reason
rep.outcome = "skipped"
elif not rep.skipped and xfailed:
if call.excinfo:
Expand Down
138 changes: 138 additions & 0 deletions testing/test_skipping.py
Original file line number Diff line number Diff line change
Expand Up @@ -1489,3 +1489,141 @@ def test_exit_reason_only():
)
result = pytester.runpytest(p)
result.stdout.fnmatch_lines("*_pytest.outcomes.Exit: foo*")


class TestMarkXFailWithFailAndXFail:
def test_marked_xfail_with_reason_pytest_fail_with_reason(
self, pytester: Pytester
) -> None:
item = pytester.getitem(
"""
import pytest
@pytest.mark.xfail(reason="reason mark.xfail")
def test_func():
pytest.fail("reason pytest.fail")
"""
)
reports = runtestprotocol(item, log=False)
assert len(reports) == 3
callreport = reports[1]
assert callreport.skipped
assert callreport.wasxfail == "reason mark.xfail"

def test_marked_xfail_with_reason_pytest_fail_without_reason(
self, pytester: Pytester
) -> None:
item = pytester.getitem(
"""
import pytest
@pytest.mark.xfail(reason="reason mark.xfail")
def test_func():
pytest.fail()
"""
)
reports = runtestprotocol(item, log=False)
assert len(reports) == 3
callreport = reports[1]
assert callreport.skipped
assert callreport.wasxfail == "reason mark.xfail"

def test_marked_xfail_without_reason_pytest_fail_with_reason(
self, pytester: Pytester
) -> None:
item = pytester.getitem(
"""
import pytest
@pytest.mark.xfail
def test_func():
pytest.fail("reason pytest.fail")
"""
)
reports = runtestprotocol(item, log=False)
assert len(reports) == 3
callreport = reports[1]
assert callreport.skipped
assert callreport.wasxfail == "reason pytest.fail"

def test_marked_xfail_without_reason_pytest_fail_without_reason(
self, pytester: Pytester
) -> None:
item = pytester.getitem(
"""
import pytest
@pytest.mark.xfail
def test_func():
pytest.fail()
"""
)
reports = runtestprotocol(item, log=False)
assert len(reports) == 3
callreport = reports[1]
assert callreport.skipped
assert callreport.wasxfail == ""

def test_marked_xfail_with_reason_pytest_xfail_with_reason(
self, pytester: Pytester
) -> None:
item = pytester.getitem(
"""
import pytest
@pytest.mark.xfail(reason="reason mark.xfail")
def test_func():
pytest.xfail("reason pytest.xfail")
"""
)
reports = runtestprotocol(item, log=False)
assert len(reports) == 3
callreport = reports[1]
assert callreport.skipped
assert callreport.wasxfail == "reason mark.xfail"

def test_marked_xfail_with_reason_pytest_xfail_without_reason(
self, pytester: Pytester
) -> None:
item = pytester.getitem(
"""
import pytest
@pytest.mark.xfail(reason="reason mark.xfail")
def test_func():
pytest.xfail()
"""
)
reports = runtestprotocol(item, log=False)
assert len(reports) == 3
callreport = reports[1]
assert callreport.skipped
assert callreport.wasxfail == "reason mark.xfail"

def test_marked_xfail_without_reason_pytest_xfail_with_reason(
self, pytester: Pytester
) -> None:
item = pytester.getitem(
"""
import pytest
@pytest.mark.xfail
def test_func():
pytest.xfail("reason pytest.xfail")
"""
)
reports = runtestprotocol(item, log=False)
assert len(reports) == 3
callreport = reports[1]
assert callreport.skipped
assert callreport.wasxfail == "reason pytest.xfail"

def test_marked_xfail_without_reason_pytest_xfail_without_reason(
self, pytester: Pytester
) -> None:
item = pytester.getitem(
"""
import pytest
@pytest.mark.xfail
def test_func():
pytest.xfail()
"""
)
reports = runtestprotocol(item, log=False)
assert len(reports) == 3
callreport = reports[1]
assert callreport.skipped
assert callreport.wasxfail == ""
Loading