fixes #1259 - take finalized nodes out of the mapping
this allows double node id usage for file based items
This commit is contained in:
parent
7b20288c2b
commit
8bf7e7cc4b
|
@ -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
|
||||||
-----
|
-----
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue