From 82ba645a2ec1c64a588c58d1b12239136ee4b99f Mon Sep 17 00:00:00 2001 From: holger krekel Date: Sat, 13 Nov 2010 21:03:28 +0100 Subject: [PATCH] fix skip reporting over distributed testing. if we have a "skip" report rep.longrepr will now be a 3-tuple (path, lineno, message) --- _pytest/resultlog.py | 5 +++-- _pytest/runner.py | 27 ++++++++++++++++++++------- _pytest/skipping.py | 4 ++-- _pytest/terminal.py | 2 +- pytest.py | 2 +- setup.py | 2 +- testing/test_runner.py | 9 +++++++-- testing/test_skipping.py | 15 +++++++-------- 8 files changed, 42 insertions(+), 24 deletions(-) diff --git a/_pytest/resultlog.py b/_pytest/resultlog.py index f4555860c..fd9e324ae 100644 --- a/_pytest/resultlog.py +++ b/_pytest/resultlog.py @@ -74,17 +74,18 @@ class ResultLog(object): elif report.failed: longrepr = str(report.longrepr) elif report.skipped: - longrepr = str(report.longrepr.reprcrash.message) + longrepr = str(report.longrepr[2]) self.log_outcome(report, code, longrepr) def pytest_collectreport(self, report): if not report.passed: if report.failed: code = "F" + longrepr = str(report.longrepr.reprcrash) else: assert report.skipped code = "S" - longrepr = str(report.longrepr.reprcrash) + longrepr = "%s:%d: %s" % report.longrepr self.log_outcome(report, code, longrepr) def pytest_internalerror(self, excrepr): diff --git a/_pytest/runner.py b/_pytest/runner.py index 6673ccf53..d65087ae8 100644 --- a/_pytest/runner.py +++ b/_pytest/runner.py @@ -111,9 +111,21 @@ class CallInfo: status = "result: %r" % (self.result,) return "" % (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): def toterminal(self, out): longrepr = self.longrepr + if hasattr(self, 'node'): + out.line(getslaveinfoline(self.node)) if hasattr(longrepr, 'toterminal'): longrepr.toterminal(out) else: @@ -140,7 +152,8 @@ def pytest_runtest_makereport(item, call): longrepr = excinfo elif excinfo.errisinstance(py.test.skip.Exception): 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: outcome = "failed" if call.when == "call": @@ -189,14 +202,14 @@ class TeardownErrorReport(BaseReport): def pytest_make_collect_report(collector): call = CallInfo(collector._memocollect, "memocollect") - reason = longrepr = None + longrepr = None if not call.excinfo: outcome = "passed" else: if call.excinfo.errisinstance(py.test.skip.Exception): outcome = "skipped" - reason = str(call.excinfo.value) - longrepr = collector._repr_failure_py(call.excinfo, "line") + r = collector._repr_failure_py(call.excinfo, "line").reprcrash + longrepr = (str(r.path), r.lineno, r.message) else: outcome = "failed" errorinfo = collector.repr_failure(call.excinfo) @@ -204,15 +217,14 @@ def pytest_make_collect_report(collector): errorinfo = CollectErrorRepr(errorinfo) longrepr = errorinfo return CollectReport(collector.nodeid, outcome, longrepr, - getattr(call, 'result', None), reason) + getattr(call, 'result', None)) class CollectReport(BaseReport): - def __init__(self, nodeid, outcome, longrepr, result, reason): + def __init__(self, nodeid, outcome, longrepr, result): self.nodeid = nodeid self.outcome = outcome self.longrepr = longrepr self.result = result or [] - self.reason = reason @property def location(self): @@ -355,6 +367,7 @@ def importorskip(modname, minversion=None): optionally specified 'minversion' - otherwise call py.test.skip() with a message detailing the mismatch. """ + __tracebackhide__ = True compile(modname, '', 'eval') # to catch syntaxerrors try: mod = __import__(modname, None, None, ['__doc__']) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index 841406d87..d22f2d308 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -186,8 +186,8 @@ def cached_eval(config, expr, d): def folded_skips(skipped): d = {} for event in skipped: - entry = event.longrepr.reprcrash - key = entry.path, entry.lineno, entry.message + key = event.longrepr + assert len(key) == 3, (event, key) d.setdefault(key, []).append(event) l = [] for key, events in d.items(): diff --git a/_pytest/terminal.py b/_pytest/terminal.py index dc1a0727e..e8ddaa5d1 100644 --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -389,7 +389,7 @@ class CollectonlyReporter: msg = report.longrepr.reprcrash.message else: # XXX unify (we have CollectErrorRepr here) - msg = str(report.longrepr.longrepr) + msg = str(report.longrepr[2]) self.outindent("!!! %s !!!" % msg) #self.outindent("!!! error !!!") self._failed.append(report) diff --git a/pytest.py b/pytest.py index 7715484a0..b6d50b484 100644 --- a/pytest.py +++ b/pytest.py @@ -5,7 +5,7 @@ see http://pytest.org for documentation and details (c) Holger Krekel and others, 2004-2010 """ -__version__ = '2.0.0.dev27' +__version__ = '2.0.0.dev28' __all__ = ['main'] from _pytest.core import main, UsageError, _preloadplugins diff --git a/setup.py b/setup.py index 8823eb2df..bfce2e080 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ def main(): name='pytest', description='py.test: simple powerful testing with Python', long_description = long_description, - version='2.0.0.dev27', + version='2.0.0.dev28', url='http://pytest.org', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], diff --git a/testing/test_runner.py b/testing/test_runner.py index 6198e4fdf..9dfaba02c 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -344,13 +344,18 @@ def test_exception_printing_skip(): def test_importorskip(): importorskip = py.test.importorskip + def f(): + importorskip("asdlkj") try: sys = importorskip("sys") assert sys == py.std.sys #path = py.test.importorskip("os.path") #assert path == py.std.os.path - py.test.raises(py.test.skip.Exception, - "py.test.importorskip('alskdj')") + excinfo = py.test.raises(py.test.skip.Exception, f) + 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')") path = importorskip("py", minversion=".".join(py.__version__)) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 81c60d257..6995323c2 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -366,11 +366,10 @@ def test_skipif_class(testdir): def test_skip_reasons_folding(): - class longrepr: - class reprcrash: - path = 'xyz' - lineno = 3 - message = "justso" + path = 'xyz' + lineno = 3 + message = "justso" + longrepr = (path, lineno, message) class X: pass @@ -387,9 +386,9 @@ def test_skip_reasons_folding(): assert len(l) == 1 num, fspath, lineno, reason = l[0] assert num == 2 - assert fspath == longrepr.reprcrash.path - assert lineno == longrepr.reprcrash.lineno - assert reason == longrepr.reprcrash.message + assert fspath == path + assert lineno == lineno + assert reason == message def test_skipped_reasons_functional(testdir): testdir.makepyfile(