remove externally setting and dealing with "item.outerr" from capturing in favor of a direct interface for adding reporting sections to items.
* * * refactor makereport implementation to avoid recursion with __multicall__
This commit is contained in:
parent
cde970be69
commit
b47fdbe0a7
|
@ -151,8 +151,6 @@ class CaptureManager:
|
||||||
|
|
||||||
def resumecapture_item(self, item):
|
def resumecapture_item(self, item):
|
||||||
method = self._getmethod(item.config, item.fspath)
|
method = self._getmethod(item.config, item.fspath)
|
||||||
if not hasattr(item, 'outerr'):
|
|
||||||
item.outerr = ('', '') # we accumulate outerr on the item
|
|
||||||
return self.resumecapture(method)
|
return self.resumecapture(method)
|
||||||
|
|
||||||
def resumecapture(self, method=None):
|
def resumecapture(self, method=None):
|
||||||
|
@ -174,16 +172,10 @@ class CaptureManager:
|
||||||
self.deactivate_funcargs()
|
self.deactivate_funcargs()
|
||||||
if hasattr(self, '_capturing'):
|
if hasattr(self, '_capturing'):
|
||||||
method = self._capturing
|
method = self._capturing
|
||||||
|
del self._capturing
|
||||||
cap = self._method2capture.get(method)
|
cap = self._method2capture.get(method)
|
||||||
if cap is not None:
|
if cap is not None:
|
||||||
outerr = cap.suspend()
|
return cap.suspend()
|
||||||
del self._capturing
|
|
||||||
if item:
|
|
||||||
outerr = (item.outerr[0] + outerr[0],
|
|
||||||
item.outerr[1] + outerr[1])
|
|
||||||
return outerr
|
|
||||||
if hasattr(item, 'outerr'):
|
|
||||||
return item.outerr
|
|
||||||
return "", ""
|
return "", ""
|
||||||
|
|
||||||
def activate_funcargs(self, pyfuncitem):
|
def activate_funcargs(self, pyfuncitem):
|
||||||
|
@ -235,18 +227,14 @@ class CaptureManager:
|
||||||
self.suspendcapture()
|
self.suspendcapture()
|
||||||
|
|
||||||
@pytest.mark.tryfirst
|
@pytest.mark.tryfirst
|
||||||
def pytest_runtest_makereport(self, __multicall__, item, call):
|
def pytest_runtest_makereport(self, item, call):
|
||||||
funcarg_outerr = self.deactivate_funcargs()
|
funcarg_outerr = self.deactivate_funcargs()
|
||||||
rep = __multicall__.execute()
|
out, err = self.suspendcapture(item)
|
||||||
outerr = self.suspendcapture(item)
|
|
||||||
if funcarg_outerr is not None:
|
if funcarg_outerr is not None:
|
||||||
outerr = (outerr[0] + funcarg_outerr[0],
|
out += funcarg_outerr[0]
|
||||||
outerr[1] + funcarg_outerr[1])
|
err += funcarg_outerr[1]
|
||||||
addouterr(rep, outerr)
|
item.add_report_section(call.when, "out", out)
|
||||||
if not rep.passed or rep.when == "teardown":
|
item.add_report_section(call.when, "err", err)
|
||||||
outerr = ('', '')
|
|
||||||
item.outerr = outerr
|
|
||||||
return rep
|
|
||||||
|
|
||||||
error_capsysfderror = "cannot use capsys and capfd at the same time"
|
error_capsysfderror = "cannot use capsys and capfd at the same time"
|
||||||
|
|
||||||
|
|
|
@ -108,12 +108,14 @@ class LogXML(object):
|
||||||
))
|
))
|
||||||
|
|
||||||
def _write_captured_output(self, report):
|
def _write_captured_output(self, report):
|
||||||
sec = dict(report.sections)
|
for capname in ('out', 'err'):
|
||||||
for name in ('out', 'err'):
|
allcontent = ""
|
||||||
content = sec.get("Captured std%s" % name)
|
for name, content in report.get_sections("Captured std%s" %
|
||||||
if content:
|
capname):
|
||||||
tag = getattr(Junit, 'system-'+name)
|
allcontent += content
|
||||||
self.append(tag(bin_xml_escape(content)))
|
if allcontent:
|
||||||
|
tag = getattr(Junit, 'system-'+capname)
|
||||||
|
self.append(tag(bin_xml_escape(allcontent)))
|
||||||
|
|
||||||
def append(self, obj):
|
def append(self, obj):
|
||||||
self.tests[-1].append(obj)
|
self.tests[-1].append(obj)
|
||||||
|
|
|
@ -233,6 +233,7 @@ class Node(object):
|
||||||
|
|
||||||
# used for storing artificial fixturedefs for direct parametrization
|
# used for storing artificial fixturedefs for direct parametrization
|
||||||
self._name2pseudofixturedef = {}
|
self._name2pseudofixturedef = {}
|
||||||
|
|
||||||
#self.extrainit()
|
#self.extrainit()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -469,6 +470,14 @@ class Item(Node):
|
||||||
"""
|
"""
|
||||||
nextitem = None
|
nextitem = None
|
||||||
|
|
||||||
|
def __init__(self, name, parent=None, config=None, session=None):
|
||||||
|
super(Item, self).__init__(name, parent, config, session)
|
||||||
|
self._report_sections = []
|
||||||
|
|
||||||
|
def add_report_section(self, when, key, content):
|
||||||
|
if content:
|
||||||
|
self._report_sections.append((when, key, content))
|
||||||
|
|
||||||
def reportinfo(self):
|
def reportinfo(self):
|
||||||
return self.fspath, None, ""
|
return self.fspath, None, ""
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,8 @@ class pytestPDB:
|
||||||
if item is not None:
|
if item is not None:
|
||||||
capman = item.config.pluginmanager.getplugin("capturemanager")
|
capman = item.config.pluginmanager.getplugin("capturemanager")
|
||||||
out, err = capman.suspendcapture()
|
out, err = capman.suspendcapture()
|
||||||
if hasattr(item, 'outerr'):
|
#if hasattr(item, 'outerr'):
|
||||||
item.outerr = (item.outerr[0] + out, item.outerr[1] + err)
|
# item.outerr = (item.outerr[0] + out, item.outerr[1] + err)
|
||||||
tw = py.io.TerminalWriter()
|
tw = py.io.TerminalWriter()
|
||||||
tw.line()
|
tw.line()
|
||||||
tw.sep(">", "PDB set_trace (IO-capturing turned off)")
|
tw.sep(">", "PDB set_trace (IO-capturing turned off)")
|
||||||
|
|
|
@ -178,6 +178,11 @@ class BaseReport(object):
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
out.line("<unprintable longrepr>")
|
out.line("<unprintable longrepr>")
|
||||||
|
|
||||||
|
def get_sections(self, prefix):
|
||||||
|
for name, content in self.sections:
|
||||||
|
if name.startswith(prefix):
|
||||||
|
yield prefix, content
|
||||||
|
|
||||||
passed = property(lambda x: x.outcome == "passed")
|
passed = property(lambda x: x.outcome == "passed")
|
||||||
failed = property(lambda x: x.outcome == "failed")
|
failed = property(lambda x: x.outcome == "failed")
|
||||||
skipped = property(lambda x: x.outcome == "skipped")
|
skipped = property(lambda x: x.outcome == "skipped")
|
||||||
|
@ -191,6 +196,7 @@ def pytest_runtest_makereport(item, call):
|
||||||
duration = call.stop-call.start
|
duration = call.stop-call.start
|
||||||
keywords = dict([(x,1) for x in item.keywords])
|
keywords = dict([(x,1) for x in item.keywords])
|
||||||
excinfo = call.excinfo
|
excinfo = call.excinfo
|
||||||
|
sections = []
|
||||||
if not call.excinfo:
|
if not call.excinfo:
|
||||||
outcome = "passed"
|
outcome = "passed"
|
||||||
longrepr = None
|
longrepr = None
|
||||||
|
@ -209,16 +215,18 @@ def pytest_runtest_makereport(item, call):
|
||||||
else: # exception in setup or teardown
|
else: # exception in setup or teardown
|
||||||
longrepr = item._repr_failure_py(excinfo,
|
longrepr = item._repr_failure_py(excinfo,
|
||||||
style=item.config.option.tbstyle)
|
style=item.config.option.tbstyle)
|
||||||
|
for rwhen, key, content in item._report_sections:
|
||||||
|
sections.append(("Captured std%s %s" %(key, rwhen), content))
|
||||||
return TestReport(item.nodeid, item.location,
|
return TestReport(item.nodeid, item.location,
|
||||||
keywords, outcome, longrepr, when,
|
keywords, outcome, longrepr, when,
|
||||||
duration=duration)
|
sections, duration)
|
||||||
|
|
||||||
class TestReport(BaseReport):
|
class TestReport(BaseReport):
|
||||||
""" Basic test report object (also used for setup and teardown calls if
|
""" Basic test report object (also used for setup and teardown calls if
|
||||||
they fail).
|
they fail).
|
||||||
"""
|
"""
|
||||||
def __init__(self, nodeid, location,
|
def __init__(self, nodeid, location, keywords, outcome,
|
||||||
keywords, outcome, longrepr, when, sections=(), duration=0, **extra):
|
longrepr, when, sections=(), duration=0, **extra):
|
||||||
#: normalized collection node id
|
#: normalized collection node id
|
||||||
self.nodeid = nodeid
|
self.nodeid = nodeid
|
||||||
|
|
||||||
|
|
|
@ -282,9 +282,9 @@ class TestPerTestCapturing:
|
||||||
"====* FAILURES *====",
|
"====* FAILURES *====",
|
||||||
"____*____",
|
"____*____",
|
||||||
"*test_capturing_outerr.py:8: ValueError",
|
"*test_capturing_outerr.py:8: ValueError",
|
||||||
"*--- Captured stdout ---*",
|
"*--- Captured stdout *call*",
|
||||||
"1",
|
"1",
|
||||||
"*--- Captured stderr ---*",
|
"*--- Captured stderr *call*",
|
||||||
"2",
|
"2",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
|
@ -478,10 +478,12 @@ def test_unicode_issue368(testdir):
|
||||||
path = testdir.tmpdir.join("test.xml")
|
path = testdir.tmpdir.join("test.xml")
|
||||||
log = LogXML(str(path), None)
|
log = LogXML(str(path), None)
|
||||||
ustr = py.builtin._totext("ВНИ!", "utf-8")
|
ustr = py.builtin._totext("ВНИ!", "utf-8")
|
||||||
class report:
|
from _pytest.runner import BaseReport
|
||||||
|
class Report(BaseReport):
|
||||||
longrepr = ustr
|
longrepr = ustr
|
||||||
sections = []
|
sections = []
|
||||||
nodeid = "something"
|
nodeid = "something"
|
||||||
|
report = Report()
|
||||||
|
|
||||||
# hopefully this is not too brittle ...
|
# hopefully this is not too brittle ...
|
||||||
log.pytest_sessionstart()
|
log.pytest_sessionstart()
|
||||||
|
|
Loading…
Reference in New Issue