fix skip reporting over distributed testing. if we have a "skip" report
rep.longrepr will now be a 3-tuple (path, lineno, message)
This commit is contained in:
parent
1bc444d5c8
commit
82ba645a2e
|
@ -74,17 +74,18 @@ class ResultLog(object):
|
||||||
elif report.failed:
|
elif report.failed:
|
||||||
longrepr = str(report.longrepr)
|
longrepr = str(report.longrepr)
|
||||||
elif report.skipped:
|
elif report.skipped:
|
||||||
longrepr = str(report.longrepr.reprcrash.message)
|
longrepr = str(report.longrepr[2])
|
||||||
self.log_outcome(report, code, longrepr)
|
self.log_outcome(report, code, longrepr)
|
||||||
|
|
||||||
def pytest_collectreport(self, report):
|
def pytest_collectreport(self, report):
|
||||||
if not report.passed:
|
if not report.passed:
|
||||||
if report.failed:
|
if report.failed:
|
||||||
code = "F"
|
code = "F"
|
||||||
|
longrepr = str(report.longrepr.reprcrash)
|
||||||
else:
|
else:
|
||||||
assert report.skipped
|
assert report.skipped
|
||||||
code = "S"
|
code = "S"
|
||||||
longrepr = str(report.longrepr.reprcrash)
|
longrepr = "%s:%d: %s" % report.longrepr
|
||||||
self.log_outcome(report, code, longrepr)
|
self.log_outcome(report, code, longrepr)
|
||||||
|
|
||||||
def pytest_internalerror(self, excrepr):
|
def pytest_internalerror(self, excrepr):
|
||||||
|
|
|
@ -111,9 +111,21 @@ class CallInfo:
|
||||||
status = "result: %r" % (self.result,)
|
status = "result: %r" % (self.result,)
|
||||||
return "<CallInfo when=%r %s>" % (self.when, status)
|
return "<CallInfo when=%r %s>" % (self.when, status)
|
||||||
|
|
||||||
|
def getslaveinfoline(node):
|
||||||
|
try:
|
||||||
|
return node._slaveinfocache
|
||||||
|
except AttributeError:
|
||||||
|
d = node.slaveinfo
|
||||||
|
ver = "%s.%s.%s" % d['version_info'][:3]
|
||||||
|
node._slaveinfocache = s = "[%s] %s -- Python %s %s" % (
|
||||||
|
d['id'], d['sysplatform'], ver, d['executable'])
|
||||||
|
return s
|
||||||
|
|
||||||
class BaseReport(object):
|
class BaseReport(object):
|
||||||
def toterminal(self, out):
|
def toterminal(self, out):
|
||||||
longrepr = self.longrepr
|
longrepr = self.longrepr
|
||||||
|
if hasattr(self, 'node'):
|
||||||
|
out.line(getslaveinfoline(self.node))
|
||||||
if hasattr(longrepr, 'toterminal'):
|
if hasattr(longrepr, 'toterminal'):
|
||||||
longrepr.toterminal(out)
|
longrepr.toterminal(out)
|
||||||
else:
|
else:
|
||||||
|
@ -140,7 +152,8 @@ def pytest_runtest_makereport(item, call):
|
||||||
longrepr = excinfo
|
longrepr = excinfo
|
||||||
elif excinfo.errisinstance(py.test.skip.Exception):
|
elif excinfo.errisinstance(py.test.skip.Exception):
|
||||||
outcome = "skipped"
|
outcome = "skipped"
|
||||||
longrepr = item._repr_failure_py(excinfo)
|
r = item._repr_failure_py(excinfo, "line").reprcrash
|
||||||
|
longrepr = (str(r.path), r.lineno, r.message)
|
||||||
else:
|
else:
|
||||||
outcome = "failed"
|
outcome = "failed"
|
||||||
if call.when == "call":
|
if call.when == "call":
|
||||||
|
@ -189,14 +202,14 @@ class TeardownErrorReport(BaseReport):
|
||||||
|
|
||||||
def pytest_make_collect_report(collector):
|
def pytest_make_collect_report(collector):
|
||||||
call = CallInfo(collector._memocollect, "memocollect")
|
call = CallInfo(collector._memocollect, "memocollect")
|
||||||
reason = longrepr = None
|
longrepr = None
|
||||||
if not call.excinfo:
|
if not call.excinfo:
|
||||||
outcome = "passed"
|
outcome = "passed"
|
||||||
else:
|
else:
|
||||||
if call.excinfo.errisinstance(py.test.skip.Exception):
|
if call.excinfo.errisinstance(py.test.skip.Exception):
|
||||||
outcome = "skipped"
|
outcome = "skipped"
|
||||||
reason = str(call.excinfo.value)
|
r = collector._repr_failure_py(call.excinfo, "line").reprcrash
|
||||||
longrepr = collector._repr_failure_py(call.excinfo, "line")
|
longrepr = (str(r.path), r.lineno, r.message)
|
||||||
else:
|
else:
|
||||||
outcome = "failed"
|
outcome = "failed"
|
||||||
errorinfo = collector.repr_failure(call.excinfo)
|
errorinfo = collector.repr_failure(call.excinfo)
|
||||||
|
@ -204,15 +217,14 @@ def pytest_make_collect_report(collector):
|
||||||
errorinfo = CollectErrorRepr(errorinfo)
|
errorinfo = CollectErrorRepr(errorinfo)
|
||||||
longrepr = errorinfo
|
longrepr = errorinfo
|
||||||
return CollectReport(collector.nodeid, outcome, longrepr,
|
return CollectReport(collector.nodeid, outcome, longrepr,
|
||||||
getattr(call, 'result', None), reason)
|
getattr(call, 'result', None))
|
||||||
|
|
||||||
class CollectReport(BaseReport):
|
class CollectReport(BaseReport):
|
||||||
def __init__(self, nodeid, outcome, longrepr, result, reason):
|
def __init__(self, nodeid, outcome, longrepr, result):
|
||||||
self.nodeid = nodeid
|
self.nodeid = nodeid
|
||||||
self.outcome = outcome
|
self.outcome = outcome
|
||||||
self.longrepr = longrepr
|
self.longrepr = longrepr
|
||||||
self.result = result or []
|
self.result = result or []
|
||||||
self.reason = reason
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def location(self):
|
def location(self):
|
||||||
|
@ -355,6 +367,7 @@ def importorskip(modname, minversion=None):
|
||||||
optionally specified 'minversion' - otherwise call py.test.skip()
|
optionally specified 'minversion' - otherwise call py.test.skip()
|
||||||
with a message detailing the mismatch.
|
with a message detailing the mismatch.
|
||||||
"""
|
"""
|
||||||
|
__tracebackhide__ = True
|
||||||
compile(modname, '', 'eval') # to catch syntaxerrors
|
compile(modname, '', 'eval') # to catch syntaxerrors
|
||||||
try:
|
try:
|
||||||
mod = __import__(modname, None, None, ['__doc__'])
|
mod = __import__(modname, None, None, ['__doc__'])
|
||||||
|
|
|
@ -186,8 +186,8 @@ def cached_eval(config, expr, d):
|
||||||
def folded_skips(skipped):
|
def folded_skips(skipped):
|
||||||
d = {}
|
d = {}
|
||||||
for event in skipped:
|
for event in skipped:
|
||||||
entry = event.longrepr.reprcrash
|
key = event.longrepr
|
||||||
key = entry.path, entry.lineno, entry.message
|
assert len(key) == 3, (event, key)
|
||||||
d.setdefault(key, []).append(event)
|
d.setdefault(key, []).append(event)
|
||||||
l = []
|
l = []
|
||||||
for key, events in d.items():
|
for key, events in d.items():
|
||||||
|
|
|
@ -389,7 +389,7 @@ class CollectonlyReporter:
|
||||||
msg = report.longrepr.reprcrash.message
|
msg = report.longrepr.reprcrash.message
|
||||||
else:
|
else:
|
||||||
# XXX unify (we have CollectErrorRepr here)
|
# XXX unify (we have CollectErrorRepr here)
|
||||||
msg = str(report.longrepr.longrepr)
|
msg = str(report.longrepr[2])
|
||||||
self.outindent("!!! %s !!!" % msg)
|
self.outindent("!!! %s !!!" % msg)
|
||||||
#self.outindent("!!! error !!!")
|
#self.outindent("!!! error !!!")
|
||||||
self._failed.append(report)
|
self._failed.append(report)
|
||||||
|
|
|
@ -5,7 +5,7 @@ see http://pytest.org for documentation and details
|
||||||
|
|
||||||
(c) Holger Krekel and others, 2004-2010
|
(c) Holger Krekel and others, 2004-2010
|
||||||
"""
|
"""
|
||||||
__version__ = '2.0.0.dev27'
|
__version__ = '2.0.0.dev28'
|
||||||
__all__ = ['main']
|
__all__ = ['main']
|
||||||
|
|
||||||
from _pytest.core import main, UsageError, _preloadplugins
|
from _pytest.core import main, UsageError, _preloadplugins
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -22,7 +22,7 @@ def main():
|
||||||
name='pytest',
|
name='pytest',
|
||||||
description='py.test: simple powerful testing with Python',
|
description='py.test: simple powerful testing with Python',
|
||||||
long_description = long_description,
|
long_description = long_description,
|
||||||
version='2.0.0.dev27',
|
version='2.0.0.dev28',
|
||||||
url='http://pytest.org',
|
url='http://pytest.org',
|
||||||
license='MIT license',
|
license='MIT license',
|
||||||
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
|
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
|
||||||
|
|
|
@ -344,13 +344,18 @@ def test_exception_printing_skip():
|
||||||
|
|
||||||
def test_importorskip():
|
def test_importorskip():
|
||||||
importorskip = py.test.importorskip
|
importorskip = py.test.importorskip
|
||||||
|
def f():
|
||||||
|
importorskip("asdlkj")
|
||||||
try:
|
try:
|
||||||
sys = importorskip("sys")
|
sys = importorskip("sys")
|
||||||
assert sys == py.std.sys
|
assert sys == py.std.sys
|
||||||
#path = py.test.importorskip("os.path")
|
#path = py.test.importorskip("os.path")
|
||||||
#assert path == py.std.os.path
|
#assert path == py.std.os.path
|
||||||
py.test.raises(py.test.skip.Exception,
|
excinfo = py.test.raises(py.test.skip.Exception, f)
|
||||||
"py.test.importorskip('alskdj')")
|
path = py.path.local(excinfo.getrepr().reprcrash.path)
|
||||||
|
# check that importorskip reports the actual call
|
||||||
|
# in this test the test_runner.py file
|
||||||
|
assert path.purebasename == "test_runner"
|
||||||
py.test.raises(SyntaxError, "py.test.importorskip('x y z')")
|
py.test.raises(SyntaxError, "py.test.importorskip('x y z')")
|
||||||
py.test.raises(SyntaxError, "py.test.importorskip('x=y')")
|
py.test.raises(SyntaxError, "py.test.importorskip('x=y')")
|
||||||
path = importorskip("py", minversion=".".join(py.__version__))
|
path = importorskip("py", minversion=".".join(py.__version__))
|
||||||
|
|
|
@ -366,11 +366,10 @@ def test_skipif_class(testdir):
|
||||||
|
|
||||||
|
|
||||||
def test_skip_reasons_folding():
|
def test_skip_reasons_folding():
|
||||||
class longrepr:
|
|
||||||
class reprcrash:
|
|
||||||
path = 'xyz'
|
path = 'xyz'
|
||||||
lineno = 3
|
lineno = 3
|
||||||
message = "justso"
|
message = "justso"
|
||||||
|
longrepr = (path, lineno, message)
|
||||||
|
|
||||||
class X:
|
class X:
|
||||||
pass
|
pass
|
||||||
|
@ -387,9 +386,9 @@ def test_skip_reasons_folding():
|
||||||
assert len(l) == 1
|
assert len(l) == 1
|
||||||
num, fspath, lineno, reason = l[0]
|
num, fspath, lineno, reason = l[0]
|
||||||
assert num == 2
|
assert num == 2
|
||||||
assert fspath == longrepr.reprcrash.path
|
assert fspath == path
|
||||||
assert lineno == longrepr.reprcrash.lineno
|
assert lineno == lineno
|
||||||
assert reason == longrepr.reprcrash.message
|
assert reason == message
|
||||||
|
|
||||||
def test_skipped_reasons_functional(testdir):
|
def test_skipped_reasons_functional(testdir):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
|
|
Loading…
Reference in New Issue