@@ -1865,6 +1865,91 @@ def test_two(setup_output):
18651865 assert (expected in system_err_text ) is expect_err
18661866
18671867
1868+ def test_interlaced_reports_nodeid_collision (pytester : Pytester ) -> None :
1869+ pytester .makeconftest (
1870+ """
1871+ import pytest
1872+ from _pytest.runner import call_and_report
1873+
1874+ _reports = []
1875+
1876+ @pytest.hookimpl(tryfirst=True)
1877+ def pytest_runtest_protocol(item, nextitem):
1878+ item.ihook.pytest_runtest_logstart(
1879+ nodeid=item.nodeid, location=item.location
1880+ )
1881+ reports = [call_and_report(item, "setup", log=False)]
1882+ if reports[0].passed:
1883+ reports.append(call_and_report(item, "call", log=False))
1884+ reports.append(
1885+ call_and_report(item, "teardown", log=False, nextitem=nextitem)
1886+ )
1887+ item.ihook.pytest_runtest_logfinish(
1888+ nodeid=item.nodeid, location=item.location
1889+ )
1890+
1891+ _reports.append(reports)
1892+ if nextitem is not None:
1893+ return True
1894+
1895+ ihook = item.ihook
1896+ for reports in _reports:
1897+ ihook.pytest_runtest_logreport(report=reports[0])
1898+ for reports in _reports:
1899+ if len(reports) == 3:
1900+ ihook.pytest_runtest_logreport(report=reports[1])
1901+ for reports in reversed(_reports):
1902+ ihook.pytest_runtest_logreport(report=reports[-1])
1903+ return True
1904+
1905+ @pytest.hookimpl(hookwrapper=True, tryfirst=True)
1906+ def pytest_runtest_logreport(report):
1907+ if report.when in ("setup", "call", "teardown"):
1908+ report.nodeid = "collided::nodeid"
1909+ sections = []
1910+ for name, content in report.sections:
1911+ if name.startswith("Captured "):
1912+ if name.endswith(f" {report.when}"):
1913+ sections.append((name, content))
1914+ else:
1915+ sections.append((name, content))
1916+ report.sections = sections
1917+ yield
1918+ """
1919+ )
1920+ pytester .makepyfile (
1921+ """
1922+ import sys
1923+ import pytest
1924+
1925+ @pytest.fixture
1926+ def setup_output(request):
1927+ print(f"SETUP_STDOUT_{request.node.name}")
1928+ sys.stderr.write(f"SETUP_STDERR_{request.node.name}\\ n")
1929+
1930+ def test_one(setup_output):
1931+ print("CALL_STDOUT_test_one")
1932+ sys.stderr.write("CALL_STDERR_test_one\\ n")
1933+
1934+ def test_two(setup_output):
1935+ print("CALL_STDOUT_test_two")
1936+ sys.stderr.write("CALL_STDERR_test_two\\ n")
1937+ """
1938+ )
1939+
1940+ xml_path = pytester .path .joinpath ("junit.xml" )
1941+ result = pytester .runpytest (
1942+ f"--junitxml={ xml_path } " ,
1943+ "--override-ini=junit_family=xunit1" ,
1944+ "--override-ini=junit_logging=all" ,
1945+ )
1946+ assert result .ret == 0
1947+
1948+ root = ET .parse (xml_path ).getroot ()
1949+ assert not list (root .iter ("system-out" ))
1950+ assert not list (root .iter ("system-err" ))
1951+
1952+
18681953@parametrize_families
18691954def test_logging_passing_tests_disabled_does_not_log_test_output (
18701955 pytester : Pytester , run_and_parse : RunAndParse , xunit_family : str
0 commit comments