From b2077ed2eca835a3649bd55de14f4b5d4bae9c35 Mon Sep 17 00:00:00 2001 From: hpk Date: Sat, 4 Apr 2009 22:19:18 +0200 Subject: [PATCH] [svn r63630] some more code to prepare for substituting the fixture/runtest code, using more plugins. --HG-- branch : trunk --- py/test/defaultconftest.py | 2 +- py/test/plugin/api.py | 5 +- py/test/plugin/pytest_default.py | 5 + py/test/plugin/pytest_pdb.py | 9 ++ py/test/runner.py | 57 +++++++----- py/test/testing/test_runner.py | 91 +++++++++++++++++++ ..._and_setup.py => test_setup_functional.py} | 70 -------------- 7 files changed, 146 insertions(+), 93 deletions(-) create mode 100644 py/test/plugin/pytest_pdb.py create mode 100644 py/test/testing/test_runner.py rename py/test/testing/{test_fixture_and_setup.py => test_setup_functional.py} (65%) diff --git a/py/test/defaultconftest.py b/py/test/defaultconftest.py index 93d5465c4..4b0b09c22 100644 --- a/py/test/defaultconftest.py +++ b/py/test/defaultconftest.py @@ -10,5 +10,5 @@ Generator = py.test.collect.Generator Function = py.test.collect.Function Instance = py.test.collect.Instance -pytest_plugins = "default terminal xfail tmpdir execnetcleanup monkeypatch".split() +pytest_plugins = "default terminal xfail tmpdir execnetcleanup monkeypatch pdb".split() diff --git a/py/test/plugin/api.py b/py/test/plugin/api.py index b8b6d9965..1b6dcff26 100644 --- a/py/test/plugin/api.py +++ b/py/test/plugin/api.py @@ -85,9 +85,12 @@ class Events: def pyevent__itemtestreport(self, event): """ test has been run. """ - def pyevent__itemsetupreport(self, rep): + def pyevent__item_runtest_finished(self, item, excinfo, outerr): """ test has been run. """ + def pyevent__itemsetupreport(self, rep): + """ a report on running a fixture function. """ + def pyevent__deselected(self, items): """ collected items that were deselected (by keyword). """ diff --git a/py/test/plugin/pytest_default.py b/py/test/plugin/pytest_default.py index 94890f489..fc1e68dae 100644 --- a/py/test/plugin/pytest_default.py +++ b/py/test/plugin/pytest_default.py @@ -17,6 +17,11 @@ class DefaultPlugin: from py.__.test import runner return runner.ItemTestReport(item, excinfo, when, outerr) + def pyevent__item_runtest_finished(self, item, excinfo, outerr): + from py.__.test import runner + rep = runner.ItemTestReport(item, excinfo, "execute", outerr) + item.config.pytestplugins.notify("itemtestreport", rep) + def pytest_pyfunc_call(self, pyfuncitem, args, kwargs): pyfuncitem.obj(*args, **kwargs) diff --git a/py/test/plugin/pytest_pdb.py b/py/test/plugin/pytest_pdb.py new file mode 100644 index 000000000..c7aea0af5 --- /dev/null +++ b/py/test/plugin/pytest_pdb.py @@ -0,0 +1,9 @@ +from py.__.test.custompdb import post_mortem + +class PdbPlugin: + def pytest_item_runtest_finished(self, item, excinfo, outerr): + if excinfo and item.config.option.usepdb: + tw = py.io.TerminalWriter() + repr = excinfo.getrepr() + repr.toterminal(tw) + post_mortem(excinfo._excinfo[2]) diff --git a/py/test/runner.py b/py/test/runner.py index c073d131b..1c1b88686 100644 --- a/py/test/runner.py +++ b/py/test/runner.py @@ -166,7 +166,6 @@ class CollectionReport(BaseReport): class ItemSetupReport(BaseReport): """ Test Execution Report. """ failed = passed = skipped = False - def __init__(self, item, excinfo=None, outerr=None): self.item = item self.outerr = outerr @@ -177,7 +176,7 @@ class ItemSetupReport(BaseReport): self.skipped = True else: self.failed = True - self.excrepr = item._repr_failure_py(excinfo, outerr) + self.excrepr = item._repr_failure_py(excinfo, []) class SetupState(object): """ shared state for setting up/tearing down test items or collectors. """ @@ -207,26 +206,42 @@ class SetupState(object): col.setup() self.stack.append(col) - def fixturecall(self, callable, item): - excinfo = None - capture = item.config._getcapture() - try: - try: - callable(item) - except (KeyboardInterrupt, SystemExit): - raise - except: - excinfo = py.code.ExceptionInfo() - finally: - outerr = capture.reset() - if not excinfo: - return True - else: + def do_setup(self, item): + excinfo, outerr = guarded_call(item.config._getcapture(), + lambda: self.prepare(item) + ) + rep = ItemSetupReport(item, excinfo, outerr) + item.config.pytestplugins.notify("itemsetupreport", rep) + return not 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) item.config.pytestplugins.notify("itemsetupreport", rep) - def setupitem(self, item): - return self.fixturecall(self.prepare, item) + 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()) + item.config.pytestplugins.notify( + "item_runtest_finished", + item=item, excinfo=excinfo, outerr=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 - def teardownitem(self, item): - self.fixturecall(self.teardown_exact, item) diff --git a/py/test/testing/test_runner.py b/py/test/testing/test_runner.py new file mode 100644 index 000000000..2e0c3d900 --- /dev/null +++ b/py/test/testing/test_runner.py @@ -0,0 +1,91 @@ + +from py.__.test.config import SetupState + +class TestSetupState: + def test_setup_ok(self, testdir): + item = testdir.getitem(""" + def setup_module(mod): + pass + def test_func(): + pass + """) + evrec = testdir.geteventrecorder(item.config) + setup = SetupState() + res = setup.do_setup(item) + assert res + + def test_setup_fails(self, testdir): + item = testdir.getitem(""" + def setup_module(mod): + print "world" + raise ValueError(42) + def test_func(): + pass + """) + evrec = testdir.geteventrecorder(item.config) + setup = SetupState() + res = setup.do_setup(item) + assert not res + rep = evrec.popevent("itemsetupreport").rep + assert rep.failed + assert not rep.skipped + assert rep.excrepr + assert "42" in str(rep.excrepr) + assert rep.outerr[0].find("world") != -1 + + def test_teardown_fails(self, testdir): + item = testdir.getitem(""" + def test_func(): + pass + def teardown_function(func): + print "13" + raise ValueError(25) + """) + evrec = testdir.geteventrecorder(item.config) + setup = SetupState() + res = setup.do_setup(item) + assert res + rep = evrec.popevent("itemsetupreport").rep + assert rep.passed + setup.do_teardown(item) + rep = evrec.popevent("itemsetupreport").rep + assert rep.item == item + assert rep.failed + assert not rep.passed + assert "13" in rep.outerr[0] + assert "25" in str(rep.excrepr) + + def test_setupitem_skips(self, testdir): + item = testdir.getitem(""" + import py + def setup_module(mod): + py.test.skip("17") + def test_func(): + pass + """) + evrec = testdir.geteventrecorder(item.config) + setup = SetupState() + setup.do_setup(item) + rep = evrec.popevent("itemsetupreport").rep + assert not rep.failed + assert rep.skipped + assert rep.excrepr + assert "17" in str(rep.excrepr) + + def test_runtest_ok(self, testdir): + item = testdir.getitem("def test_func(): pass") + evrec = testdir.geteventrecorder(item.config) + setup = SetupState() + setup.do_fixture_and_runtest(item) + rep = evrec.popevent("itemtestreport").event + assert rep.passed + + def test_runtest_fails(self, testdir): + item = testdir.getitem("def test_func(): assert 0") + evrec = testdir.geteventrecorder(item.config) + setup = SetupState() + setup.do_fixture_and_runtest(item) + event = evrec.popevent("item_runtest_finished") + assert event.excinfo + + diff --git a/py/test/testing/test_fixture_and_setup.py b/py/test/testing/test_setup_functional.py similarity index 65% rename from py/test/testing/test_fixture_and_setup.py rename to py/test/testing/test_setup_functional.py index 16ddca502..838bac64e 100644 --- a/py/test/testing/test_fixture_and_setup.py +++ b/py/test/testing/test_setup_functional.py @@ -139,73 +139,3 @@ def test_method_setup_uses_fresh_instances(testdir): """) sorter.assertoutcome(passed=4, failed=0) -from py.__.test.config import SetupState - -class TestSetupState: - def test_setupitem_works(self, testdir): - item = testdir.getitem(""" - def setup_module(mod): - pass - def test_func(): - pass - """) - evrec = testdir.geteventrecorder(item.config) - setup = SetupState() - res = setup.setupitem(item) - assert res - - def test_setupitem_fails(self, testdir): - item = testdir.getitem(""" - def setup_module(mod): - print "world" - raise ValueError(42) - def test_func(): - pass - """) - evrec = testdir.geteventrecorder(item.config) - setup = SetupState() - res = setup.setupitem(item) - assert not res - rep = evrec.popevent("itemsetupreport").rep - assert rep.failed - assert not rep.skipped - assert rep.excrepr - assert "42" in str(rep.excrepr) - assert rep.outerr[0].find("world") != -1 - - def test_teardownitem_fails(self, testdir): - item = testdir.getitem(""" - def test_func(): - pass - def teardown_function(func): - print "13" - raise ValueError(25) - """) - evrec = testdir.geteventrecorder(item.config) - setup = SetupState() - res = setup.setupitem(item) - assert res - setup.teardownitem(item) - rep = evrec.popevent("itemsetupreport").rep - assert rep.item == item - assert rep.failed - assert not rep.passed - assert "13" in rep.outerr[0] - assert "25" in str(rep.excrepr) - - def test_setupitem_skips(self, testdir): - item = testdir.getitem(""" - import py - def setup_module(mod): - py.test.skip("17") - def test_func(): - pass - """) - evrec = testdir.geteventrecorder(item.config) - setup = SetupState() - setup.setupitem(item) - rep = evrec.popevent("itemsetupreport").rep - assert not rep.failed - assert rep.skipped - assert rep.excrepr - assert "17" in str(rep.excrepr)