From 192f6992d2c82f129c1951a212970a678c176e79 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 12 Jul 2019 14:35:34 -0300 Subject: [PATCH] Include root tag in generated XML (#5550) Include root tag in generated XML --- 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 00000000000..c9c9386e996 --- /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 3972113cbb0..6f21a0638d8 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -667,18 +667,17 @@ def pytest_sessionfinish(self): ) 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 4c21c94d365..a09f16fb720 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -47,6 +47,16 @@ def find_first_by_tag(self, tag): 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: @@ -81,7 +91,7 @@ def tag(self): return self.__node.tagName @property - def next_siebling(self): + def next_sibling(self): return type(self)(self.__node.nextSibling) @@ -390,11 +400,11 @@ def test_fail(): 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() @@ -1101,6 +1111,20 @@ def test_x(i): 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( """