From bba69f207b26a99e97e4327ca84692d954e08e72 Mon Sep 17 00:00:00 2001 From: hpk Date: Tue, 7 Apr 2009 16:27:57 +0200 Subject: [PATCH] [svn r63797] introduce a clean "guardedcall" interface for performing calls with exception catching and stdout/stderr capturing --HG-- branch : trunk --- py/test/config.py | 22 +++++++++++++++++++++ py/test/runner.py | 35 ++++++++-------------------------- py/test/testing/test_config.py | 35 +++++++++++++++++++++++++++++++--- 3 files changed, 62 insertions(+), 30 deletions(-) diff --git a/py/test/config.py b/py/test/config.py index 9e37f6a52..563fe761d 100644 --- a/py/test/config.py +++ b/py/test/config.py @@ -286,6 +286,28 @@ class Config(object): roots.append(pydir) return roots + def guardedcall(self, func): + excinfo = result = None + capture = self._getcapture() + try: + try: + result = func() + except KeyboardInterrupt: + raise + except: + excinfo = py.code.ExceptionInfo() + finally: + stdout, stderr = capture.reset() + return CallResult(result, excinfo, stdout, stderr) + +class CallResult: + def __init__(self, result, excinfo, stdout, stderr): + self.stdout = stdout + self.stderr = stderr + self.outerr = (self.stdout, self.stderr) + self.excinfo = excinfo + if excinfo is None: + self.result = result # # helpers diff --git a/py/test/runner.py b/py/test/runner.py index a99183054..22a6848b9 100644 --- a/py/test/runner.py +++ b/py/test/runner.py @@ -198,41 +198,22 @@ class SetupState(object): self.stack.append(col) def do_setup(self, item): - excinfo, outerr = guarded_call(item.config._getcapture(), - lambda: self.prepare(item) - ) - rep = ItemSetupReport(item, excinfo, outerr) + call = item.config.guardedcall(lambda: self.prepare(item)) + rep = ItemSetupReport(item, call.excinfo, call.outerr) item.config.pytestplugins.notify("itemsetupreport", rep) - return not excinfo + return not call.excinfo def do_teardown(self, item): - excinfo, outerr = guarded_call(item.config._getcapture(), - lambda: self.teardown_exact(item) - ) - if excinfo: - rep = ItemSetupReport(item, excinfo, outerr) + call = item.config.guardedcall(lambda: self.teardown_exact(item)) + if call.excinfo: + rep = ItemSetupReport(item, call.excinfo, call.outerr) item.config.pytestplugins.notify("itemsetupreport", rep) def do_fixture_and_runtest(self, item): """ setup fixture and perform actual item.runtest(). """ if self.do_setup(item): - excinfo, outerr = guarded_call(item.config._getcapture(), - lambda: item.runtest()) + call = item.config.guardedcall(lambda: item.runtest()) item.config.pytestplugins.notify( "item_runtest_finished", - item=item, excinfo=excinfo, outerr=outerr) + item=item, excinfo=call.excinfo, outerr=call.outerr) self.do_teardown(item) - -def guarded_call(capture, call): - excinfo = None - try: - try: - call() - except (KeyboardInterrupt, Exit): - raise - except: - excinfo = py.code.ExceptionInfo() - finally: - outerr = capture.reset() - return excinfo, outerr - diff --git a/py/test/testing/test_config.py b/py/test/testing/test_config.py index 3d9076446..be014fc6c 100644 --- a/py/test/testing/test_config.py +++ b/py/test/testing/test_config.py @@ -137,8 +137,7 @@ class TestConfigAPI: assert pl[1] == somepath def test_setsessionclass_and_initsession(self, testdir): - from py.__.test.config import Config - config = Config() + config = testdir.Config() class Session1: def __init__(self, config): self.config = config @@ -149,7 +148,6 @@ class TestConfigAPI: py.test.raises(ValueError, "config.setsessionclass(Session1)") - class TestConfigApi_getcolitems: def test_getcolitems_onedir(self, tmpdir): config = py.test.config._reparse([tmpdir]) @@ -214,6 +212,37 @@ class TestConfigApi_getcolitems: assert col.config is config +class TestGuardedCall: + def test_guardedcall_ok(self, testdir): + config = testdir.parseconfig() + def myfunc(x): + print x + print >>py.std.sys.stderr, "hello" + return 7 + call = config.guardedcall(lambda: myfunc(3)) + assert call.excinfo is None + assert call.result == 7 + assert call.stdout.startswith("3") + assert call.stderr.startswith("hello") + + def test_guardedcall_fail(self, testdir): + config = testdir.parseconfig() + def myfunc(x): + print x + raise ValueError(17) + call = config.guardedcall(lambda: myfunc(3)) + assert call.excinfo + assert call.excinfo.type == ValueError + assert not hasattr(call, 'result') + assert call.stdout.startswith("3") + assert not call.stderr + + def test_guardedcall_keyboardinterrupt(self, testdir): + config = testdir.parseconfig() + def myfunc(): + raise KeyboardInterrupt + py.test.raises(KeyboardInterrupt, config.guardedcall, myfunc) + class TestOptionEffects: def test_boxed_option_default(self, testdir): tmpdir = testdir.tmpdir.ensure("subdir", dir=1)