diff --git a/_pytest/capture.py b/_pytest/capture.py index 71af4b348..b3d425b04 100644 --- a/_pytest/capture.py +++ b/_pytest/capture.py @@ -173,8 +173,7 @@ class CaptureManager: if funcarg_outerr is not None: outerr = (outerr[0] + funcarg_outerr[0], outerr[1] + funcarg_outerr[1]) - if not rep.passed: - addouterr(rep, outerr) + addouterr(rep, outerr) if not rep.passed or rep.when == "teardown": outerr = ('', '') item.outerr = outerr diff --git a/_pytest/junitxml.py b/_pytest/junitxml.py index 63a402616..b4ffccfe2 100644 --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -107,11 +107,20 @@ class LogXML(object): time=getattr(report, 'duration', 0) )) + def _write_captured_output(self, report): + sec = dict(report.sections) + for name in ('out', 'err'): + content = sec.get("Captured std%s" % name) + if content: + tag = getattr(Junit, 'system-'+name) + self.append(tag(bin_xml_escape(content))) + def append(self, obj): self.tests[-1].append(obj) def append_pass(self, report): self.passed += 1 + self._write_captured_output(report) def append_failure(self, report): #msg = str(report.longrepr.reprtraceback.extraline) @@ -120,16 +129,11 @@ class LogXML(object): Junit.skipped(message="xfail-marked test passes unexpectedly")) self.skipped += 1 else: - sec = dict(report.sections) fail = Junit.failure(message="test failure") fail.append(str(report.longrepr)) self.append(fail) - for name in ('out', 'err'): - content = sec.get("Captured std%s" % name) - if content: - tag = getattr(Junit, 'system-'+name) - self.append(tag(bin_xml_escape(content))) self.failed += 1 + self._write_captured_output(report) def append_collect_failure(self, report): #msg = str(report.longrepr.reprtraceback.extraline) @@ -162,6 +166,7 @@ class LogXML(object): message=skipreason )) self.skipped += 1 + self._write_captured_output(report) def pytest_runtest_logreport(self, report): if report.passed: diff --git a/_pytest/pdb.py b/_pytest/pdb.py index 470e13def..c9471401a 100644 --- a/_pytest/pdb.py +++ b/_pytest/pdb.py @@ -70,16 +70,21 @@ class PdbInvoke: tw.sep(">", "traceback") rep.toterminal(tw) tw.sep(">", "entering PDB") - # A doctest.UnexpectedException is not useful for post_mortem. - # Use the underlying exception instead: - if isinstance(call.excinfo.value, py.std.doctest.UnexpectedException): - tb = call.excinfo.value.exc_info[2] - else: - tb = call.excinfo._excinfo[2] + + tb = self._postmortem_traceback(call.excinfo) post_mortem(tb) rep._pdbshown = True return rep + @staticmethod + def _postmortem_traceback(excinfo): + # A doctest.UnexpectedException is not useful for post_mortem. + # Use the underlying exception instead: + if isinstance(excinfo.value, py.std.doctest.UnexpectedException): + return excinfo.value.exc_info[2] + else: + return excinfo._excinfo[2] + def post_mortem(t): pdb = py.std.pdb class Pdb(pdb.Pdb): diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index a3c248489..dbb814961 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -282,13 +282,35 @@ class TestPython: if not sys.platform.startswith("java"): assert "hx" in fnode.toxml() + def test_pass_captures_stdout(self, testdir): + testdir.makepyfile(""" + def test_pass(): + print('hello-stdout') + """) + result, dom = runandparse(testdir) + node = dom.getElementsByTagName("testsuite")[0] + pnode = node.getElementsByTagName("testcase")[0] + systemout = pnode.getElementsByTagName("system-out")[0] + assert "hello-stdout" in systemout.toxml() + + def test_pass_captures_stderr(self, testdir): + testdir.makepyfile(""" + import sys + def test_pass(): + sys.stderr.write('hello-stderr') + """) + result, dom = runandparse(testdir) + node = dom.getElementsByTagName("testsuite")[0] + pnode = node.getElementsByTagName("testcase")[0] + systemout = pnode.getElementsByTagName("system-err")[0] + assert "hello-stderr" in systemout.toxml() + def test_mangle_testnames(): from _pytest.junitxml import mangle_testnames names = ["a/pything.py", "Class", "()", "method"] newnames = mangle_testnames(names) assert newnames == ["a.pything", "Class", "method"] - def test_dont_configure_on_slaves(tmpdir): gotten = [] class FakeConfig: