Skip to content

Commit a8c23ec

Browse files
committed
Improve coverage
1 parent d6ec3ce commit a8c23ec

File tree

2 files changed

+31
-11
lines changed

2 files changed

+31
-11
lines changed

src/_pytest/subtests.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,9 @@ def _new(
129129
def subtests(request: SubRequest) -> Subtests:
130130
"""Provides subtests functionality."""
131131
capmam = request.node.config.pluginmanager.get_plugin("capturemanager")
132-
if capmam is not None:
133-
suspend_capture_ctx = capmam.global_and_fixture_disabled
134-
else:
135-
suspend_capture_ctx = nullcontext
132+
suspend_capture_ctx = (
133+
capmam.global_and_fixture_disabled if capmam is not None else nullcontext
134+
)
136135
return Subtests(request.node.ihook, suspend_capture_ctx, request, _ispytest=True)
137136

138137

@@ -377,11 +376,9 @@ def pytest_report_teststatus(
377376
category = "xfailed"
378377
short = "y" # x letter is used for regular xfail, y for subtest xfail
379378
status = "SUBXFAIL"
380-
elif outcome == "passed":
381-
category = "xpassed"
382-
short = "Y" # X letter is used for regular xpass, Y for subtest xpass
383-
status = "SUBXPASS"
384-
else:
379+
# outcome == "passed" in an xfail is only possible via a @pytest.mark.xfail mark, which
380+
# is not applicable to a subtest, which only handles pytest.xfail().
381+
else: # pragma: no cover
385382
# This should not normally happen, unless some plugin is setting wasxfail without
386383
# the correct outcome. Pytest expects the call outcome to be either skipped or
387384
# passed in case of xfail.

testing/test_subtests.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import sys
44
from typing import Literal
55

6+
from _pytest.subtests import SubtestContext
7+
from _pytest.subtests import SubtestReport
68
import pytest
79

810

@@ -642,9 +644,10 @@ def test(subtests):
642644
"""
643645
)
644646

645-
def test_capturing(self, pytester: pytest.Pytester) -> None:
647+
@pytest.mark.parametrize("mode", ["fd", "sys"])
648+
def test_capturing(self, pytester: pytest.Pytester, mode: str) -> None:
646649
self.create_file(pytester)
647-
result = pytester.runpytest()
650+
result = pytester.runpytest(f"--capture={mode}")
648651
result.stdout.fnmatch_lines(
649652
[
650653
"*__ test (i='A') __*",
@@ -952,3 +955,23 @@ def test(subtests):
952955
"* 3 failed in *",
953956
]
954957
)
958+
959+
960+
def test_serialization() -> None:
961+
from _pytest.subtests import pytest_report_from_serializable
962+
from _pytest.subtests import pytest_report_to_serializable
963+
964+
report = SubtestReport(
965+
"test_foo::test_foo",
966+
("test_foo.py", 12, ""),
967+
keywords={},
968+
outcome="passed",
969+
when="call",
970+
longrepr=None,
971+
context=SubtestContext(msg="custom message", kwargs=dict(i=10)),
972+
)
973+
data = pytest_report_to_serializable(report)
974+
assert data is not None
975+
new_report = pytest_report_from_serializable(data)
976+
assert new_report is not None
977+
assert new_report.context == SubtestContext(msg="custom message", kwargs=dict(i=10))

0 commit comments

Comments
 (0)