Skip to content

Commit 69c5fde

Browse files
committed
Handle backwards-compatiblity
1 parent 1e6af9c commit 69c5fde

File tree

1 file changed

+54
-10
lines changed

1 file changed

+54
-10
lines changed

src/_pytest/junitxml.py

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,37 @@ def repl(matchobj):
6969
return py.xml.raw(illegal_xml_re.sub(repl, py.xml.escape(arg)))
7070

7171

72+
def merge_family(left, right):
73+
result = {}
74+
for kl, vl in left.items():
75+
for kr, vr in right.items():
76+
if not isinstance(vl, list):
77+
raise NotImplementedError(type(vl))
78+
result[kl] = vl + vr
79+
left.update(result)
80+
81+
82+
families = {}
83+
families["_base"] = {"testcase": ["classname", "name"]}
84+
families["_base_old"] = {"testcase": ["file", "line", "url"]}
85+
86+
# xUnit 1.x inherits old attributes
87+
families["xunit1"] = families["_base"].copy()
88+
merge_family(families["xunit1"], families["_base_old"])
89+
90+
# Alias "old" to xUnit 1.x
91+
families["old"] = families["xunit1"]
92+
93+
# xUnit 2.x uses strict base attributes
94+
families["xunit2"] = families["_base"]
95+
96+
7297
class _NodeReporter(object):
7398
def __init__(self, nodeid, xml):
74-
7599
self.id = nodeid
76100
self.xml = xml
77101
self.add_stats = self.xml.add_stats
102+
self.family = self.xml.family
78103
self.duration = 0
79104
self.properties = []
80105
self.nodes = []
@@ -110,12 +135,31 @@ def record_testreport(self, testreport):
110135
classnames = names[:-1]
111136
if self.xml.prefix:
112137
classnames.insert(0, self.xml.prefix)
113-
attrs = {"classname": ".".join(classnames), "name": bin_xml_escape(names[-1])}
138+
attrs = {
139+
"classname": ".".join(classnames),
140+
"name": bin_xml_escape(names[-1]),
141+
"file": testreport.location[0],
142+
}
143+
if testreport.location[1] is not None:
144+
attrs["line"] = testreport.location[1]
114145
if hasattr(testreport, "url"):
115146
attrs["url"] = testreport.url
116147
self.attrs = attrs
117148
self.attrs.update(existing_attrs) # restore any user-defined attributes
118149

150+
# Preserve old testcase behavior
151+
if self.family == "old":
152+
return
153+
154+
# Purge attributes not permitted by this test family
155+
# This includes custom attributes, because they are not valid here.
156+
# TODO: Convert invalid attributes to properties to preserve "something"
157+
temp_attrs = {}
158+
for key in self.attrs.keys():
159+
if key in families[self.family]["testcase"]:
160+
temp_attrs[key] = self.attrs[key]
161+
self.attrs = temp_attrs
162+
119163
def to_xml(self):
120164
testcase = Junit.testcase(time="%.3f" % self.duration, **self.attrs)
121165
testcase.append(self.make_properties_node())
@@ -234,7 +278,7 @@ def append_skipped(self, report):
234278
def finalize(self):
235279
data = self.to_xml().unicode(indent=0)
236280
self.__dict__.clear()
237-
self.to_xml = lambda: py.xml.raw(data)
281+
self.raw = lambda: py.xml.raw(data)
238282

239283

240284
@pytest.fixture
@@ -356,19 +400,15 @@ def mangle_test_address(address):
356400

357401
class LogXML(object):
358402
def __init__(
359-
self,
360-
logfile,
361-
prefix,
362-
suite_name="pytest",
363-
logging="no",
364-
report_duration="total",
403+
self, logfile, prefix, suite_name="pytest", logging="no", report_duration="total", family="old"
365404
):
366405
logfile = os.path.expanduser(os.path.expandvars(logfile))
367406
self.logfile = os.path.normpath(os.path.abspath(logfile))
368407
self.prefix = prefix
369408
self.suite_name = suite_name
370409
self.logging = logging
371410
self.report_duration = report_duration
411+
self.family = family
372412
self.stats = dict.fromkeys(["error", "passed", "failure", "skipped"], 0)
373413
self.node_reporters = {} # nodeid -> _NodeReporter
374414
self.node_reporters_ordered = []
@@ -542,7 +582,7 @@ def pytest_sessionfinish(self):
542582
logfile.write(
543583
Junit.testsuite(
544584
self._get_global_properties_node(),
545-
[x.to_xml() for x in self.node_reporters_ordered],
585+
[x.raw() for x in self.node_reporters_ordered],
546586
name=self.suite_name,
547587
errors=self.stats["error"],
548588
failures=self.stats["failure"],
@@ -553,6 +593,10 @@ def pytest_sessionfinish(self):
553593
)
554594
logfile.close()
555595

596+
# TODO: GET RID OF
597+
with open(self.logfile) as logfile:
598+
print(logfile.read())
599+
556600
def pytest_terminal_summary(self, terminalreporter):
557601
terminalreporter.write_sep("-", "generated xml file: %s" % (self.logfile))
558602

0 commit comments

Comments
 (0)