]> granicus.if.org Git - python/commitdiff
Issue #10979. unittest stdout buffering now works with class and module setup and...
authorMichael Foord <michael@python.org>
Thu, 17 Mar 2011 17:44:18 +0000 (13:44 -0400)
committerMichael Foord <michael@python.org>
Thu, 17 Mar 2011 17:44:18 +0000 (13:44 -0400)
Lib/unittest/result.py
Lib/unittest/suite.py
Lib/unittest/test/test_result.py
Misc/NEWS

index 3dc7154b732b45c495c1f5746d0652ee6d7d7d34..44bf1862e4f9e893bea404d293a8e3f9685df678 100644 (file)
@@ -59,6 +59,9 @@ class TestResult(object):
         "Called when the given test is about to be run"
         self.testsRun += 1
         self._mirrorOutput = False
+        self._setupStdout()
+
+    def _setupStdout(self):
         if self.buffer:
             if self._stderr_buffer is None:
                 self._stderr_buffer = io.StringIO()
@@ -74,6 +77,10 @@ class TestResult(object):
 
     def stopTest(self, test):
         """Called when the given test has been run"""
+        self._restoreStdout()
+        self._mirrorOutput = False
+
+    def _restoreStdout(self):
         if self.buffer:
             if self._mirrorOutput:
                 output = sys.stdout.getvalue()
@@ -93,7 +100,6 @@ class TestResult(object):
             self._stdout_buffer.truncate()
             self._stderr_buffer.seek(0)
             self._stderr_buffer.truncate()
-        self._mirrorOutput = False
 
     def stopTestRun(self):
         """Called once after all tests are executed.
index 77ce089187305b74630d40b7a0ce75e80ae54aa0..38bd6b861df726fa97160998041454e8489dfe8e 100644 (file)
@@ -8,6 +8,11 @@ from . import util
 __unittest = True
 
 
+def _call_if_exists(parent, attr):
+    func = getattr(parent, attr, lambda: None)
+    func()
+
+
 class BaseTestSuite(object):
     """A simple test suite that doesn't provide class or module shared fixtures.
     """
@@ -133,6 +138,7 @@ class TestSuite(BaseTestSuite):
 
         setUpClass = getattr(currentClass, 'setUpClass', None)
         if setUpClass is not None:
+            _call_if_exists(result, '_setupStdout')
             try:
                 setUpClass()
             except Exception as e:
@@ -142,6 +148,8 @@ class TestSuite(BaseTestSuite):
                 className = util.strclass(currentClass)
                 errorName = 'setUpClass (%s)' % className
                 self._addClassOrModuleLevelException(result, e, errorName)
+            finally:
+                _call_if_exists(result, '_restoreStdout')
 
     def _get_previous_module(self, result):
         previousModule = None
@@ -167,6 +175,7 @@ class TestSuite(BaseTestSuite):
             return
         setUpModule = getattr(module, 'setUpModule', None)
         if setUpModule is not None:
+            _call_if_exists(result, '_setupStdout')
             try:
                 setUpModule()
             except Exception as e:
@@ -175,6 +184,8 @@ class TestSuite(BaseTestSuite):
                 result._moduleSetUpFailed = True
                 errorName = 'setUpModule (%s)' % currentModule
                 self._addClassOrModuleLevelException(result, e, errorName)
+            finally:
+                _call_if_exists(result, '_restoreStdout')
 
     def _addClassOrModuleLevelException(self, result, exception, errorName):
         error = _ErrorHolder(errorName)
@@ -198,6 +209,7 @@ class TestSuite(BaseTestSuite):
 
         tearDownModule = getattr(module, 'tearDownModule', None)
         if tearDownModule is not None:
+            _call_if_exists(result, '_setupStdout')
             try:
                 tearDownModule()
             except Exception as e:
@@ -205,6 +217,8 @@ class TestSuite(BaseTestSuite):
                     raise
                 errorName = 'tearDownModule (%s)' % previousModule
                 self._addClassOrModuleLevelException(result, e, errorName)
+            finally:
+                _call_if_exists(result, '_restoreStdout')
 
     def _tearDownPreviousClass(self, test, result):
         previousClass = getattr(result, '_previousTestClass', None)
@@ -220,6 +234,7 @@ class TestSuite(BaseTestSuite):
 
         tearDownClass = getattr(previousClass, 'tearDownClass', None)
         if tearDownClass is not None:
+            _call_if_exists(result, '_setupStdout')
             try:
                 tearDownClass()
             except Exception as e:
@@ -228,7 +243,8 @@ class TestSuite(BaseTestSuite):
                 className = util.strclass(previousClass)
                 errorName = 'tearDownClass (%s)' % className
                 self._addClassOrModuleLevelException(result, e, errorName)
-
+            finally:
+                _call_if_exists(result, '_restoreStdout')
 
 
 class _ErrorHolder(object):
index 64798a1098e14682091923d8e9f52c8c3ae2f8da..1c58e61bb2bb96be0eaceb48d8bd3a977e8622a0 100644 (file)
@@ -497,5 +497,72 @@ class TestOutputBuffering(unittest.TestCase):
             self.assertEqual(result._original_stderr.getvalue(), expectedErrMessage)
             self.assertMultiLineEqual(message, expectedFullMessage)
 
+    def testBufferSetupClass(self):
+        result = unittest.TestResult()
+        result.buffer = True
+
+        class Foo(unittest.TestCase):
+            @classmethod
+            def setUpClass(cls):
+                1/0
+            def test_foo(self):
+                pass
+        suite = unittest.TestSuite([Foo('test_foo')])
+        suite(result)
+        self.assertEqual(len(result.errors), 1)
+
+    def testBufferTearDownClass(self):
+        result = unittest.TestResult()
+        result.buffer = True
+
+        class Foo(unittest.TestCase):
+            @classmethod
+            def tearDownClass(cls):
+                1/0
+            def test_foo(self):
+                pass
+        suite = unittest.TestSuite([Foo('test_foo')])
+        suite(result)
+        self.assertEqual(len(result.errors), 1)
+
+    def testBufferSetUpModule(self):
+        result = unittest.TestResult()
+        result.buffer = True
+
+        class Foo(unittest.TestCase):
+            def test_foo(self):
+                pass
+        class Module(object):
+            @staticmethod
+            def setUpModule():
+                1/0
+
+        Foo.__module__ = 'Module'
+        sys.modules['Module'] = Module
+        self.addCleanup(sys.modules.pop, 'Module')
+        suite = unittest.TestSuite([Foo('test_foo')])
+        suite(result)
+        self.assertEqual(len(result.errors), 1)
+
+    def testBufferTearDownModule(self):
+        result = unittest.TestResult()
+        result.buffer = True
+
+        class Foo(unittest.TestCase):
+            def test_foo(self):
+                pass
+        class Module(object):
+            @staticmethod
+            def tearDownModule():
+                1/0
+
+        Foo.__module__ = 'Module'
+        sys.modules['Module'] = Module
+        self.addCleanup(sys.modules.pop, 'Module')
+        suite = unittest.TestSuite([Foo('test_foo')])
+        suite(result)
+        self.assertEqual(len(result.errors), 1)
+
+
 if __name__ == '__main__':
     unittest.main()
index 1bce6681c619eb908940b93259cbb0e4ab4ead9e..6d6ba33cf27353bdc848b5c279863548cc3e9484 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.2.1?
 Core and Builtins
 -----------------
 
+- Issue #10979: unittest stdout buffering now works with class and module
+  setup and teardown.
+
 - Issue #11510: Fixed optimizer bug which turned "a,b={1,1}" into "a,b=(1,1)".
 
 - Issue #11432: A bug was introduced in subprocess.Popen on posix systems with