[py-svn] py-trunk commit 4b97998e25d9: fix capturing to be more careful during teardown when a setup never happened (due to e.g. an error in user-provided runtest_setup code)

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Wed Dec 30 10:42:42 CET 2009


# HG changeset patch -- Bitbucket.org
# Project py-trunk
# URL http://bitbucket.org/hpk42/py-trunk/overview/
# User holger krekel <holger at merlinux.eu>
# Date 1262128287 -3600
# Node ID 4b97998e25d97dd9441dd2fed22d8ae835fb45bb
# Parent 42bec69042c5559dfd8689bf116ac67f87f1e068
fix capturing to be more careful during teardown when a setup never happened (due to e.g. an error in user-provided runtest_setup code)

--- a/testing/plugin/test_pytest_capture.py
+++ b/testing/plugin/test_pytest_capture.py
@@ -379,3 +379,15 @@ class TestCaptureFuncarg:
         ])
         assert result.ret == 2
 
+def test_setup_failure_does_not_kill_capturing(testdir):
+    sub1 = testdir.mkpydir("sub1")
+    sub1.join("conftest.py").write(py.code.Source("""
+        def pytest_runtest_setup(item):
+            raise ValueError(42)
+    """))
+    sub1.join("test_mod.py").write("def test_func1(): pass")
+    result = testdir.runpytest(testdir.tmpdir, '--traceconfig')
+    result.stdout.fnmatch_lines([
+        "*ValueError(42)*",
+        "*1 error*"
+    ])

--- a/py/plugin/pytest_capture.py
+++ b/py/plugin/pytest_capture.py
@@ -161,16 +161,20 @@ class CaptureManager:
                 cap.resume()
         self._capturing = method 
 
-    def suspendcapture(self):
+    def suspendcapture(self, item=None):
         self.deactivate_funcargs()
-        method = self._capturing
-        if method != "no":
-            cap = self._method2capture[method]
-            outerr = cap.suspend()
-        else:
-            outerr = "", ""
-        del self._capturing
-        return outerr 
+        if hasattr(self, '_capturing'):
+            method = self._capturing
+            if method != "no":
+                cap = self._method2capture[method]
+                outerr = cap.suspend()
+            else:
+                outerr = "", ""
+            del self._capturing
+            if item:
+                outerr = (item.outerr[0] + outerr[0], item.outerr[1] + outerr[1])
+            return outerr 
+        return "", ""
 
     def activate_funcargs(self, pyfuncitem):
         if not hasattr(pyfuncitem, 'funcargs'):
@@ -210,9 +214,6 @@ class CaptureManager:
     def pytest_runtest_teardown(self, item):
         self.resumecapture_item(item)
 
-    def pytest_runtest_teardown(self, item):
-        self.resumecapture_item(item)
-
     def pytest__teardown_final(self, __multicall__, session):
         method = self._getmethod(session.config, None)
         self.resumecapture(method)
@@ -231,8 +232,7 @@ class CaptureManager:
     def pytest_runtest_makereport(self, __multicall__, item, call):
         self.deactivate_funcargs()
         rep = __multicall__.execute()
-        outerr = self.suspendcapture()
-        outerr = (item.outerr[0] + outerr[0], item.outerr[1] + outerr[1])
+        outerr = self.suspendcapture(item)
         if not rep.passed:
             addouterr(rep, outerr)
         if not rep.passed or rep.when == "teardown":

--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,6 +9,9 @@ Changes between 1.X and 1.1.1
 
 - new "pytestconfig" funcarg allows access to test config object
 
+- robustify capturing to survive if custom pytest_runtest_setup 
+  code failed and prevented the capturing setup code from running. 
+
 - make py.test.* helpers provided by default plugins visible early -
   works transparently both for pydoc and for interactive sessions
   which will regularly see e.g. py.test.mark and py.test.importorskip.



More information about the pytest-commit mailing list