Skip to content

Commit

Permalink
Fix user_properties not saved to XML if fixture errors during teardown
Browse files Browse the repository at this point in the history
Move handling of user_properties to `finalize()`.

Previously if a fixture failed during teardown, `pytest_runtest_logreport` would not be called with "teardown", resulting in the user properties not being saved on the JUnit XML file.

Fixes: pytest-dev#11367
  • Loading branch information
fruch committed Sep 3, 2023
1 parent 4e3a087 commit 917ce9a
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 3 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -170,6 +170,7 @@ Ian Lesperance
Ilya Konstantinov
Ionuț Turturică
Isaac Virshup
Israel Fruchter
Itxaso Aizpurua
Iwan Briquemont
Jaap Broekhuizen
Expand Down
1 change: 1 addition & 0 deletions changelog/11367.bugfix.rst
@@ -0,0 +1 @@
Fixed bug where `user_properties` where not being saved in the JUnit XML file if a fixture failed during teardown.
7 changes: 4 additions & 3 deletions src/_pytest/junitxml.py
Expand Up @@ -502,6 +502,10 @@ def finalize(self, report: TestReport) -> None:
# Local hack to handle xdist report order.
workernode = getattr(report, "node", None)
reporter = self.node_reporters.pop((nodeid, workernode))

for propname, propvalue in report.user_properties:
reporter.add_property(propname, str(propvalue))

if reporter is not None:
reporter.finalize()

Expand Down Expand Up @@ -599,9 +603,6 @@ def pytest_runtest_logreport(self, report: TestReport) -> None:
reporter = self._opentestcase(report)
reporter.write_captured_output(report)

for propname, propvalue in report.user_properties:
reporter.add_property(propname, str(propvalue))

self.finalize(report)
report_wid = getattr(report, "worker_id", None)
report_ii = getattr(report, "item_index", None)
Expand Down
30 changes: 30 additions & 0 deletions testing/test_junitxml.py
Expand Up @@ -1228,6 +1228,36 @@ def test_record(record_property, other):
result.stdout.fnmatch_lines(["*= 1 passed in *"])


def test_record_property_on_test_and_teardown_failure(
pytester: Pytester, run_and_parse: RunAndParse
) -> None:
pytester.makepyfile(
"""
import pytest
@pytest.fixture
def other(record_property):
record_property("bar", 1)
yield
assert 0
def test_record(record_property, other):
record_property("foo", "<1")
assert 0
"""
)
result, dom = run_and_parse()
node = dom.find_first_by_tag("testsuite")
tnodes = node.find_by_tag("testcase")
for tnode in tnodes:
psnode = tnode.find_first_by_tag("properties")
assert psnode, f"testcase didn't had expected properties:\n{tnode}"
pnodes = psnode.find_by_tag("property")
pnodes[0].assert_attr(name="bar", value="1")
pnodes[1].assert_attr(name="foo", value="<1")
result.stdout.fnmatch_lines(["*= 1 failed, 1 error *"])


def test_record_property_same_name(
pytester: Pytester, run_and_parse: RunAndParse
) -> None:
Expand Down

0 comments on commit 917ce9a

Please sign in to comment.