[py-svn] pytest commit 22f3981d50c8: fix #6 : allow skip/xfail/pdb with trial by hacking the raw exception info out from trial

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Wed Nov 24 11:50:10 CET 2010


# HG changeset patch -- Bitbucket.org
# Project pytest
# URL http://bitbucket.org/hpk42/pytest/overview
# User holger krekel <holger at merlinux.eu>
# Date 1290595735 -3600
# Node ID 22f3981d50c80bea055c39d0e1310dc45e0d5f75
# Parent  9d430445abb6f3235910b3d3d679a16135588e39
fix #6 : allow skip/xfail/pdb with trial by hacking the raw exception info out from trial

--- a/tox.ini
+++ b/tox.ini
@@ -25,6 +25,13 @@ commands=
   py.test -n3 -rfsxX \
         --junitxml={envlogdir}/junit-{envname}.xml []
 
+[testenv:trial]
+changedir=.
+basepython=python2.6
+deps=:pypi:twisted
+commands=
+  py.test -rsxf \
+        --junitxml={envlogdir}/junit-{envname}.xml [testing/test_unittest.py]
 [testenv:doctest]
 changedir=.
 commands=py.test --doctest-modules _pytest

--- a/_pytest/unittest.py
+++ b/_pytest/unittest.py
@@ -44,8 +44,8 @@ class TestCaseFunction(pytest.Function):
         pass
 
     def _addexcinfo(self, rawexcinfo):
-        #__tracebackhide__ = True
-        assert rawexcinfo
+        # unwrap potential exception info (see twisted trial support below)
+        rawexcinfo = getattr(rawexcinfo, '_rawexcinfo', rawexcinfo)
         try:
             self._excinfo = py.code.ExceptionInfo(rawexcinfo)
         except TypeError:
@@ -60,10 +60,10 @@ class TestCaseFunction(pytest.Function):
                 except:
                     pytest.fail("ERROR: Unknown Incompatible Exception "
                         "representation:\n%r" %(rawexcinfo,), pytrace=False)
+            except KeyboardInterrupt:
+                raise
             except pytest.fail.Exception:
                 self._excinfo = py.code.ExceptionInfo()
-            except KeyboardInterrupt:
-                raise
 
     def addError(self, testcase, rawexcinfo):
         self._addexcinfo(rawexcinfo)
@@ -84,3 +84,30 @@ def pytest_runtest_makereport(item, call
             call.excinfo = item._excinfo
             item._excinfo = None
             del call.result
+
+# twisted trial support
+def pytest_runtest_protocol(item, __multicall__):
+    if isinstance(item, TestCaseFunction):
+        if 'twisted.trial.unittest' in sys.modules:
+            ut = sys.modules['twisted.python.failure']
+            Failure__init__ = ut.Failure.__init__.im_func
+            check_testcase_implements_trial_reporter()
+            def excstore(self, exc_value=None, exc_type=None, exc_tb=None):
+                if exc_value is None:
+                    self._rawexcinfo = sys.exc_info()
+                else:
+                    self._rawexcinfo = (exc_value, exc_type, exc_tb)
+                Failure__init__(self, exc_value, exc_type, exc_tb)
+            ut.Failure.__init__ = excstore
+            try:
+                return __multicall__.execute()
+            finally:
+                ut.Failure.__init__ = Failure__init__
+
+def check_testcase_implements_trial_reporter(done=[]):
+    if done:
+        return
+    from zope.interface import classImplements
+    from twisted.trial.itrial import IReporter
+    classImplements(TestCaseFunction, IReporter)
+    done.append(1)

--- a/pytest.py
+++ b/pytest.py
@@ -5,7 +5,7 @@ see http://pytest.org for documentation 
 
 (c) Holger Krekel and others, 2004-2010
 """
-__version__ = '2.0.0.dev36'
+__version__ = '2.0.0.dev37'
 __all__ = ['main']
 
 from _pytest.core import main, UsageError, _preloadplugins

--- a/_pytest/pdb.py
+++ b/_pytest/pdb.py
@@ -44,11 +44,11 @@ def pytest_runtest_makereport():
 class PdbInvoke:
     @pytest.mark.tryfirst
     def pytest_runtest_makereport(self, item, call, __multicall__):
+        rep = __multicall__.execute()
         if not call.excinfo or \
             call.excinfo.errisinstance(pytest.skip.Exception) or \
             call.excinfo.errisinstance(py.std.bdb.BdbQuit):
-            return
-        rep = __multicall__.execute()
+            return rep
         if "xfail" in rep.keywords:
             return rep
         # we assume that the above execute() suspended capturing

--- 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.dev36',
+        version='2.0.0.dev37',
         url='http://pytest.org',
         license='MIT license',
         platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],

--- a/testing/test_unittest.py
+++ b/testing/test_unittest.py
@@ -185,3 +185,107 @@ def test_testcase_totally_incompatible_e
     item.addError(None, 42)
     excinfo = item._excinfo
     assert 'ERROR: Unknown Incompatible' in str(excinfo.getrepr())
+
+
+
+class TestTrialUnittest:
+    def setup_class(cls):
+        pytest.importorskip("twisted.trial.unittest")
+
+    def test_trial_exceptions_with_skips(self, testdir):
+        testdir.makepyfile("""
+            from twisted.trial import unittest
+            import pytest
+            class TC(unittest.TestCase):
+                def test_hello(self):
+                    pytest.skip("skip_in_method")
+                @pytest.mark.skipif("sys.version_info != 1")
+                def test_hello2(self):
+                    pass
+                @pytest.mark.xfail(reason="iwanto")
+                def test_hello3(self):
+                    assert 0
+                def test_hello4(self):
+                    pytest.xfail("i2wanto")
+
+            class TC2(unittest.TestCase):
+                def setup_class(cls):
+                    pytest.skip("skip_in_setup_class")
+                def test_method(self):
+                    pass
+        """)
+        result = testdir.runpytest("-rxs")
+        assert result.ret == 0
+        result.stdout.fnmatch_lines_random([
+            "*skip_in_setup_class*",
+            "*iwanto*",
+            "*i2wanto*",
+            "*sys.version_info*",
+            "*skip_in_method*",
+            "*3 skipped*2 xfail*",
+        ])
+
+    def test_trial_pdb(self, testdir):
+        p = testdir.makepyfile("""
+            from twisted.trial import unittest
+            import pytest
+            class TC(unittest.TestCase):
+                def test_hello(self):
+                    assert 0, "hellopdb"
+        """)
+        child = testdir.spawn_pytest(p)
+        child.expect("hellopdb")
+        child.sendeof()
+
+def test_djangolike_testcase(testdir):
+    # contributed from Morten Breekevold
+    testdir.makepyfile("""
+        from unittest import TestCase, main
+
+        class DjangoLikeTestCase(TestCase):
+
+            def setUp(self):
+                print ("setUp()")
+
+            def test_presetup_has_been_run(self):
+                print ("test_thing()")
+                self.assertTrue(hasattr(self, 'was_presetup'))
+
+            def tearDown(self):
+                print ("tearDown()")
+
+            def __call__(self, result=None):
+                try:
+                    self._pre_setup()
+                except (KeyboardInterrupt, SystemExit):
+                    raise
+                except Exception:
+                    import sys
+                    result.addError(self, sys.exc_info())
+                    return
+                super(DjangoLikeTestCase, self).__call__(result)
+                try:
+                    self._post_teardown()
+                except (KeyboardInterrupt, SystemExit):
+                    raise
+                except Exception:
+                    import sys
+                    result.addError(self, sys.exc_info())
+                    return
+
+            def _pre_setup(self):
+                print ("_pre_setup()")
+                self.was_presetup = True
+
+            def _post_teardown(self):
+                print ("_post_teardown()")
+    """)
+    result = testdir.runpytest("-s")
+    assert result.ret == 0
+    result.stdout.fnmatch_lines([
+        "*_pre_setup()*",
+        "*setUp()*",
+        "*test_thing()*",
+        "*tearDown()*",
+        "*_post_teardown()*",
+    ])



More information about the pytest-commit mailing list