fixes #1259 - take finalized nodes out of the mapping

this allows double node id usage for file based items
This commit is contained in:
Ronny Pfannschmidt 2015-12-16 19:07:36 +01:00
parent 7b20288c2b
commit 8bf7e7cc4b
3 changed files with 52 additions and 10 deletions

View File

@ -1,6 +1,7 @@
2.8.6.dev1 2.8.6.dev1
---------- ----------
- fix #1259: allow for double nodeids in junitxml
2.8.5 2.8.5
----- -----

View File

@ -71,7 +71,6 @@ class _NodeReporter(object):
self.testcase = None self.testcase = None
self.attrs = {} self.attrs = {}
def append(self, node): def append(self, node):
self.xml.add_stats(type(node).__name__) self.xml.add_stats(type(node).__name__)
self.nodes.append(node) self.nodes.append(node)
@ -82,7 +81,6 @@ class _NodeReporter(object):
self.property_insert_order.append(name) self.property_insert_order.append(name)
self.properties[name] = bin_xml_escape(value) self.properties[name] = bin_xml_escape(value)
def make_properties_node(self): def make_properties_node(self):
"""Return a Junit node containing custom properties, if any. """Return a Junit node containing custom properties, if any.
""" """
@ -93,7 +91,6 @@ class _NodeReporter(object):
]) ])
return '' return ''
def record_testreport(self, testreport): def record_testreport(self, testreport):
assert not self.testcase assert not self.testcase
names = mangle_testnames(testreport.nodeid.split("::")) names = mangle_testnames(testreport.nodeid.split("::"))
@ -182,7 +179,6 @@ class _NodeReporter(object):
message=skipreason)) message=skipreason))
self._write_captured_output(report) self._write_captured_output(report)
def finalize(self): def finalize(self):
data = self.to_xml().unicode(indent=0) data = self.to_xml().unicode(indent=0)
self.__dict__.clear() self.__dict__.clear()
@ -262,6 +258,14 @@ class LogXML(object):
self.node_reporters = {} # nodeid -> _NodeReporter self.node_reporters = {} # nodeid -> _NodeReporter
self.node_reporters_ordered = [] self.node_reporters_ordered = []
def finalize(self, report):
nodeid = getattr(report, 'nodeid', report)
# local hack to handle xdist report order
slavenode = getattr(report, 'node', None)
reporter = self.node_reporters.pop((nodeid, slavenode))
if reporter is not None:
reporter.finalize()
def node_reporter(self, report): def node_reporter(self, report):
nodeid = getattr(report, 'nodeid', report) nodeid = getattr(report, 'nodeid', report)
# local hack to handle xdist report order # local hack to handle xdist report order
@ -270,7 +274,7 @@ class LogXML(object):
key = nodeid, slavenode key = nodeid, slavenode
if key in self.node_reporters: if key in self.node_reporters:
#TODO: breasks for --dist=each # TODO: breasks for --dist=each
return self.node_reporters[key] return self.node_reporters[key]
reporter = _NodeReporter(nodeid, self) reporter = _NodeReporter(nodeid, self)
self.node_reporters[key] = reporter self.node_reporters[key] = reporter
@ -324,7 +328,7 @@ class LogXML(object):
reporter.append_skipped(report) reporter.append_skipped(report)
self.update_testcase_duration(report) self.update_testcase_duration(report)
if report.when == "teardown": if report.when == "teardown":
self.node_reporter(report).finalize() self.finalize(report)
def update_testcase_duration(self, report): def update_testcase_duration(self, report):
"""accumulates total duration for nodeid from given report and updates """accumulates total duration for nodeid from given report and updates

View File

@ -18,6 +18,7 @@ def runandparse(testdir, *args):
def assert_attr(node, **kwargs): def assert_attr(node, **kwargs):
__tracebackhide__ = True __tracebackhide__ = True
def nodeval(node, name): def nodeval(node, name):
anode = node.getAttributeNode(name) anode = node.getAttributeNode(name)
if anode is not None: if anode is not None:
@ -667,10 +668,12 @@ def test_runs_twice(testdir):
pass pass
''') ''')
result = testdir.runpytest(f, f, '--junitxml', testdir.tmpdir.join("test.xml")) result = testdir.runpytest(
assert 'INTERNALERROR' not in str(result.stdout) f, f, '--junitxml', testdir.tmpdir.join("test.xml"))
assert 'INTERNALERROR' not in result.stdout.str()
@pytest.mark.xfail(reason='hangs', run=False)
def test_runs_twice_xdist(testdir): def test_runs_twice_xdist(testdir):
pytest.importorskip('xdist') pytest.importorskip('xdist')
f = testdir.makepyfile(''' f = testdir.makepyfile('''
@ -678,7 +681,41 @@ def test_runs_twice_xdist(testdir):
pass pass
''') ''')
result = testdir.runpytest(f, result = testdir.runpytest(
f,
'--dist', 'each', '--tx', '2*popen', '--dist', 'each', '--tx', '2*popen',
'--junitxml', testdir.tmpdir.join("test.xml")) '--junitxml', testdir.tmpdir.join("test.xml"))
assert 'INTERNALERROR' not in str(result.stdout) assert 'INTERNALERROR' not in result.stdout.str()
def test_fancy_items_regression(testdir):
' issue 1259'
testdir.makeconftest("""
import pytest
class FunItem(pytest.Item):
def runtest(self):
pass
class NoFunItem(pytest.Item):
def runtest(self):
pass
class FunCollector(pytest.File):
def collect(self):
return [
FunItem('a', self),
NoFunItem('a', self),
]
def pytest_collect_file(path, parent):
return FunCollector(path, parent)
""")
testdir.makepyfile('''
def test_pass():
pass
''')
result = testdir.runpytest(
'--junitxml', testdir.tmpdir.join("test.xml"))
assert 'INTERNALERROR' not in result.stdout.str()