From a43ba78d3bde1630a42aaa95776687d3886891e6 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 3 Jul 2019 20:34:12 -0300 Subject: [PATCH] Include root tag in generated XML Fix #5477 --- changelog/5477.bugfix.rst | 1 + src/_pytest/junitxml.py | 21 ++++++++++----------- testing/test_junitxml.py | 30 +++++++++++++++++++++++++++--- 3 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 changelog/5477.bugfix.rst diff --git a/changelog/5477.bugfix.rst b/changelog/5477.bugfix.rst new file mode 100644 index 000000000..c9c9386e9 --- /dev/null +++ b/changelog/5477.bugfix.rst @@ -0,0 +1 @@ +The XML file produced by ``--junitxml`` now correctly contain a ```` root element. diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index ea33e606c..15c630b1d 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -657,18 +657,17 @@ class LogXML: ) logfile.write('') - logfile.write( - Junit.testsuite( - self._get_global_properties_node(), - [x.to_xml() for x in self.node_reporters_ordered], - name=self.suite_name, - errors=self.stats["error"], - failures=self.stats["failure"], - skipped=self.stats["skipped"], - tests=numtests, - time="%.3f" % suite_time_delta, - ).unicode(indent=0) + suite_node = Junit.testsuite( + self._get_global_properties_node(), + [x.to_xml() for x in self.node_reporters_ordered], + name=self.suite_name, + errors=self.stats["error"], + failures=self.stats["failure"], + skipped=self.stats["skipped"], + tests=numtests, + time="%.3f" % suite_time_delta, ) + logfile.write(Junit.testsuites([suite_node]).unicode(indent=0)) logfile.close() def pytest_terminal_summary(self, terminalreporter): diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index bcf83b352..15643b081 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -41,6 +41,16 @@ class DomNode: def _by_tag(self, tag): return self.__node.getElementsByTagName(tag) + @property + def children(self): + return [type(self)(x) for x in self.__node.childNodes] + + @property + def get_unique_child(self): + children = self.children + assert len(children) == 1 + return children[0] + def find_nth_by_tag(self, tag, n): items = self._by_tag(tag) try: @@ -75,7 +85,7 @@ class DomNode: return self.__node.tagName @property - def next_siebling(self): + def next_sibling(self): return type(self)(self.__node.nextSibling) @@ -384,11 +394,11 @@ class TestPython: fnode = tnode.find_first_by_tag("failure") fnode.assert_attr(message="ValueError: 42") assert "ValueError" in fnode.toxml() - systemout = fnode.next_siebling + systemout = fnode.next_sibling assert systemout.tag == "system-out" assert "hello-stdout" in systemout.toxml() assert "info msg" not in systemout.toxml() - systemerr = systemout.next_siebling + systemerr = systemout.next_sibling assert systemerr.tag == "system-err" assert "hello-stderr" in systemerr.toxml() assert "info msg" not in systemerr.toxml() @@ -1094,6 +1104,20 @@ def test_random_report_log_xdist(testdir, monkeypatch): assert failed == ["test_x[22]"] +def test_root_testsuites_tag(testdir): + testdir.makepyfile( + """ + def test_x(): + pass + """ + ) + _, dom = runandparse(testdir) + root = dom.get_unique_child + assert root.tag == "testsuites" + suite_node = root.get_unique_child + assert suite_node.tag == "testsuite" + + def test_runs_twice(testdir): f = testdir.makepyfile( """