Merge pull request #809 from kevincox/junitxml-file-attribute
Add `file` and `line` attributes to junit-xml output.
This commit is contained in:
commit
9293062221
1
AUTHORS
1
AUTHORS
|
@ -39,6 +39,7 @@ Janne Vanhala
|
||||||
Jason R. Coombs
|
Jason R. Coombs
|
||||||
Jurko Gospodnetić
|
Jurko Gospodnetić
|
||||||
Katarzyna Jachim
|
Katarzyna Jachim
|
||||||
|
Kevin Cox
|
||||||
Maciek Fijalkowski
|
Maciek Fijalkowski
|
||||||
Maho
|
Maho
|
||||||
Marc Schlaich
|
Marc Schlaich
|
||||||
|
|
|
@ -67,6 +67,8 @@
|
||||||
|
|
||||||
- add a new ``--noconftest`` argument which ignores all ``conftest.py`` files.
|
- add a new ``--noconftest`` argument which ignores all ``conftest.py`` files.
|
||||||
|
|
||||||
|
- add ``file`` and ``line`` attributes to JUnit-XML output.
|
||||||
|
|
||||||
2.7.2 (compared to 2.7.1)
|
2.7.2 (compared to 2.7.1)
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
""" report test results in JUnit-XML format, for use with Hudson and build integration servers.
|
""" report test results in JUnit-XML format, for use with Hudson and build integration servers.
|
||||||
|
|
||||||
|
Output conforms to https://github.com/jenkinsci/xunit-plugin/blob/master/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
|
||||||
|
|
||||||
Based on initial code from Ross Lawley.
|
Based on initial code from Ross Lawley.
|
||||||
"""
|
"""
|
||||||
import py
|
import py
|
||||||
|
@ -93,11 +95,15 @@ class LogXML(object):
|
||||||
classnames = names[:-1]
|
classnames = names[:-1]
|
||||||
if self.prefix:
|
if self.prefix:
|
||||||
classnames.insert(0, self.prefix)
|
classnames.insert(0, self.prefix)
|
||||||
self.tests.append(Junit.testcase(
|
attrs = {
|
||||||
classname=".".join(classnames),
|
"classname": ".".join(classnames),
|
||||||
name=bin_xml_escape(names[-1]),
|
"name": bin_xml_escape(names[-1]),
|
||||||
time=0
|
"file": report.location[0],
|
||||||
))
|
"time": 0,
|
||||||
|
}
|
||||||
|
if report.location[1] is not None:
|
||||||
|
attrs["line"] = report.location[1]
|
||||||
|
self.tests.append(Junit.testcase(**attrs))
|
||||||
|
|
||||||
def _write_captured_output(self, report):
|
def _write_captured_output(self, report):
|
||||||
for capname in ('out', 'err'):
|
for capname in ('out', 'err'):
|
||||||
|
|
|
@ -70,6 +70,8 @@ class TestPython:
|
||||||
assert_attr(node, errors=1, tests=0)
|
assert_attr(node, errors=1, tests=0)
|
||||||
tnode = node.getElementsByTagName("testcase")[0]
|
tnode = node.getElementsByTagName("testcase")[0]
|
||||||
assert_attr(tnode,
|
assert_attr(tnode,
|
||||||
|
file="test_setup_error.py",
|
||||||
|
line="2",
|
||||||
classname="test_setup_error",
|
classname="test_setup_error",
|
||||||
name="test_function")
|
name="test_function")
|
||||||
fnode = tnode.getElementsByTagName("error")[0]
|
fnode = tnode.getElementsByTagName("error")[0]
|
||||||
|
@ -88,6 +90,8 @@ class TestPython:
|
||||||
assert_attr(node, skips=1)
|
assert_attr(node, skips=1)
|
||||||
tnode = node.getElementsByTagName("testcase")[0]
|
tnode = node.getElementsByTagName("testcase")[0]
|
||||||
assert_attr(tnode,
|
assert_attr(tnode,
|
||||||
|
file="test_skip_contains_name_reason.py",
|
||||||
|
line="1",
|
||||||
classname="test_skip_contains_name_reason",
|
classname="test_skip_contains_name_reason",
|
||||||
name="test_skip")
|
name="test_skip")
|
||||||
snode = tnode.getElementsByTagName("skipped")[0]
|
snode = tnode.getElementsByTagName("skipped")[0]
|
||||||
|
@ -108,6 +112,8 @@ class TestPython:
|
||||||
assert_attr(node, failures=1)
|
assert_attr(node, failures=1)
|
||||||
tnode = node.getElementsByTagName("testcase")[0]
|
tnode = node.getElementsByTagName("testcase")[0]
|
||||||
assert_attr(tnode,
|
assert_attr(tnode,
|
||||||
|
file="test_classname_instance.py",
|
||||||
|
line="1",
|
||||||
classname="test_classname_instance.TestClass",
|
classname="test_classname_instance.TestClass",
|
||||||
name="test_method")
|
name="test_method")
|
||||||
|
|
||||||
|
@ -120,6 +126,8 @@ class TestPython:
|
||||||
assert_attr(node, failures=1)
|
assert_attr(node, failures=1)
|
||||||
tnode = node.getElementsByTagName("testcase")[0]
|
tnode = node.getElementsByTagName("testcase")[0]
|
||||||
assert_attr(tnode,
|
assert_attr(tnode,
|
||||||
|
file=os.path.join("sub", "test_hello.py"),
|
||||||
|
line="0",
|
||||||
classname="sub.test_hello",
|
classname="sub.test_hello",
|
||||||
name="test_func")
|
name="test_func")
|
||||||
|
|
||||||
|
@ -151,6 +159,8 @@ class TestPython:
|
||||||
assert_attr(node, failures=1, tests=1)
|
assert_attr(node, failures=1, tests=1)
|
||||||
tnode = node.getElementsByTagName("testcase")[0]
|
tnode = node.getElementsByTagName("testcase")[0]
|
||||||
assert_attr(tnode,
|
assert_attr(tnode,
|
||||||
|
file="test_failure_function.py",
|
||||||
|
line="1",
|
||||||
classname="test_failure_function",
|
classname="test_failure_function",
|
||||||
name="test_fail")
|
name="test_fail")
|
||||||
fnode = tnode.getElementsByTagName("failure")[0]
|
fnode = tnode.getElementsByTagName("failure")[0]
|
||||||
|
@ -193,6 +203,8 @@ class TestPython:
|
||||||
|
|
||||||
tnode = node.getElementsByTagName("testcase")[index]
|
tnode = node.getElementsByTagName("testcase")[index]
|
||||||
assert_attr(tnode,
|
assert_attr(tnode,
|
||||||
|
file="test_failure_escape.py",
|
||||||
|
line="1",
|
||||||
classname="test_failure_escape",
|
classname="test_failure_escape",
|
||||||
name="test_func[%s]" % char)
|
name="test_func[%s]" % char)
|
||||||
sysout = tnode.getElementsByTagName('system-out')[0]
|
sysout = tnode.getElementsByTagName('system-out')[0]
|
||||||
|
@ -214,10 +226,14 @@ class TestPython:
|
||||||
assert_attr(node, failures=1, tests=2)
|
assert_attr(node, failures=1, tests=2)
|
||||||
tnode = node.getElementsByTagName("testcase")[0]
|
tnode = node.getElementsByTagName("testcase")[0]
|
||||||
assert_attr(tnode,
|
assert_attr(tnode,
|
||||||
|
file="test_junit_prefixing.py",
|
||||||
|
line="0",
|
||||||
classname="xyz.test_junit_prefixing",
|
classname="xyz.test_junit_prefixing",
|
||||||
name="test_func")
|
name="test_func")
|
||||||
tnode = node.getElementsByTagName("testcase")[1]
|
tnode = node.getElementsByTagName("testcase")[1]
|
||||||
assert_attr(tnode,
|
assert_attr(tnode,
|
||||||
|
file="test_junit_prefixing.py",
|
||||||
|
line="3",
|
||||||
classname="xyz.test_junit_prefixing."
|
classname="xyz.test_junit_prefixing."
|
||||||
"TestHello",
|
"TestHello",
|
||||||
name="test_hello")
|
name="test_hello")
|
||||||
|
@ -234,6 +250,8 @@ class TestPython:
|
||||||
assert_attr(node, skips=1, tests=0)
|
assert_attr(node, skips=1, tests=0)
|
||||||
tnode = node.getElementsByTagName("testcase")[0]
|
tnode = node.getElementsByTagName("testcase")[0]
|
||||||
assert_attr(tnode,
|
assert_attr(tnode,
|
||||||
|
file="test_xfailure_function.py",
|
||||||
|
line="1",
|
||||||
classname="test_xfailure_function",
|
classname="test_xfailure_function",
|
||||||
name="test_xfail")
|
name="test_xfail")
|
||||||
fnode = tnode.getElementsByTagName("skipped")[0]
|
fnode = tnode.getElementsByTagName("skipped")[0]
|
||||||
|
@ -253,6 +271,8 @@ class TestPython:
|
||||||
assert_attr(node, skips=1, tests=0)
|
assert_attr(node, skips=1, tests=0)
|
||||||
tnode = node.getElementsByTagName("testcase")[0]
|
tnode = node.getElementsByTagName("testcase")[0]
|
||||||
assert_attr(tnode,
|
assert_attr(tnode,
|
||||||
|
file="test_xfailure_xpass.py",
|
||||||
|
line="1",
|
||||||
classname="test_xfailure_xpass",
|
classname="test_xfailure_xpass",
|
||||||
name="test_xpass")
|
name="test_xpass")
|
||||||
fnode = tnode.getElementsByTagName("skipped")[0]
|
fnode = tnode.getElementsByTagName("skipped")[0]
|
||||||
|
@ -267,8 +287,10 @@ class TestPython:
|
||||||
assert_attr(node, errors=1, tests=0)
|
assert_attr(node, errors=1, tests=0)
|
||||||
tnode = node.getElementsByTagName("testcase")[0]
|
tnode = node.getElementsByTagName("testcase")[0]
|
||||||
assert_attr(tnode,
|
assert_attr(tnode,
|
||||||
|
file="test_collect_error.py",
|
||||||
#classname="test_collect_error",
|
#classname="test_collect_error",
|
||||||
name="test_collect_error")
|
name="test_collect_error")
|
||||||
|
assert tnode.getAttributeNode("line") is None
|
||||||
fnode = tnode.getElementsByTagName("error")[0]
|
fnode = tnode.getElementsByTagName("error")[0]
|
||||||
assert_attr(fnode, message="collection failure")
|
assert_attr(fnode, message="collection failure")
|
||||||
assert "SyntaxError" in fnode.toxml()
|
assert "SyntaxError" in fnode.toxml()
|
||||||
|
@ -281,8 +303,10 @@ class TestPython:
|
||||||
assert_attr(node, skips=1, tests=0)
|
assert_attr(node, skips=1, tests=0)
|
||||||
tnode = node.getElementsByTagName("testcase")[0]
|
tnode = node.getElementsByTagName("testcase")[0]
|
||||||
assert_attr(tnode,
|
assert_attr(tnode,
|
||||||
|
file="test_collect_skipped.py",
|
||||||
#classname="test_collect_error",
|
#classname="test_collect_error",
|
||||||
name="test_collect_skipped")
|
name="test_collect_skipped")
|
||||||
|
assert tnode.getAttributeNode("line") is None # py.test doesn't give us a line here.
|
||||||
fnode = tnode.getElementsByTagName("skipped")[0]
|
fnode = tnode.getElementsByTagName("skipped")[0]
|
||||||
assert_attr(fnode, message="collection skipped")
|
assert_attr(fnode, message="collection skipped")
|
||||||
|
|
||||||
|
@ -510,6 +534,7 @@ def test_unicode_issue368(testdir):
|
||||||
longrepr = ustr
|
longrepr = ustr
|
||||||
sections = []
|
sections = []
|
||||||
nodeid = "something"
|
nodeid = "something"
|
||||||
|
location = 'tests/filename.py', 42, 'TestClass.method'
|
||||||
report = Report()
|
report = Report()
|
||||||
|
|
||||||
# hopefully this is not too brittle ...
|
# hopefully this is not too brittle ...
|
||||||
|
|
Loading…
Reference in New Issue