[Python-checkins] r81874 - in python/branches/py3k: Lib/unittest/case.py Lib/unittest/suite.py Lib/unittest/test/test_runner.py Lib/unittest/test/test_setups.py

michael.foord python-checkins at python.org
Thu Jun 10 18:16:08 CEST 2010


Author: michael.foord
Date: Thu Jun 10 18:16:08 2010
New Revision: 81874

Log:
Merged revisions 81853 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r81853 | michael.foord | 2010-06-08 23:44:52 +0100 (Tue, 08 Jun 2010) | 1 line
  
  Issue 8948. cleanup functions are not run by unittest.TestCase.debug(), plus class and module teardowns are not run by unittest.TestSuite.debug().
........


Modified:
   python/branches/py3k/   (props changed)
   python/branches/py3k/Lib/unittest/case.py
   python/branches/py3k/Lib/unittest/suite.py
   python/branches/py3k/Lib/unittest/test/test_runner.py
   python/branches/py3k/Lib/unittest/test/test_setups.py

Modified: python/branches/py3k/Lib/unittest/case.py
==============================================================================
--- python/branches/py3k/Lib/unittest/case.py	(original)
+++ python/branches/py3k/Lib/unittest/case.py	Thu Jun 10 18:16:08 2010
@@ -389,6 +389,9 @@
         self.setUp()
         getattr(self, self._testMethodName)()
         self.tearDown()
+        while self._cleanups:
+            function, args, kwargs = self._cleanups.pop(-1)
+            function(*args, **kwargs)
 
     def skipTest(self, reason):
         """Skip this test."""

Modified: python/branches/py3k/Lib/unittest/suite.py
==============================================================================
--- python/branches/py3k/Lib/unittest/suite.py	(original)
+++ python/branches/py3k/Lib/unittest/suite.py	Thu Jun 10 18:16:08 2010
@@ -84,9 +84,16 @@
         self._handleModuleTearDown(result)
         return result
 
+    def debug(self):
+        """Run the tests without collecting errors in a TestResult"""
+        debug = _DebugResult()
+        self._wrapped_run(debug, True)
+        self._tearDownPreviousClass(None, debug)
+        self._handleModuleTearDown(debug)
+
     ################################
     # private methods
-    def _wrapped_run(self, result):
+    def _wrapped_run(self, result, debug=False):
         for test in self:
             if result.shouldStop:
                 break
@@ -103,8 +110,10 @@
 
             if hasattr(test, '_wrapped_run'):
                 test._wrapped_run(result)
-            else:
+            elif not debug:
                 test(result)
+            else:
+                test.debug()
 
     def _handleClassSetUp(self, test, result):
         previousClass = getattr(result, '_previousTestClass', None)
@@ -128,6 +137,8 @@
             try:
                 setUpClass()
             except Exception as e:
+                if isinstance(result, _DebugResult):
+                    raise
                 currentClass._classSetupFailed = True
                 className = util.strclass(currentClass)
                 errorName = 'setUpClass (%s)' % className
@@ -160,6 +171,8 @@
             try:
                 setUpModule()
             except Exception as e:
+                if isinstance(result, _DebugResult):
+                    raise
                 result._moduleSetUpFailed = True
                 errorName = 'setUpModule (%s)' % currentModule
                 self._addClassOrModuleLevelException(result, e, errorName)
@@ -189,6 +202,8 @@
             try:
                 tearDownModule()
             except Exception as e:
+                if isinstance(result, _DebugResult):
+                    raise
                 errorName = 'tearDownModule (%s)' % previousModule
                 self._addClassOrModuleLevelException(result, e, errorName)
 
@@ -209,6 +224,8 @@
             try:
                 tearDownClass()
             except Exception as e:
+                if isinstance(result, _DebugResult):
+                    raise
                 className = util.strclass(previousClass)
                 errorName = 'tearDownClass (%s)' % className
                 self._addClassOrModuleLevelException(result, e, errorName)
@@ -260,3 +277,10 @@
     except TypeError:
         return True
     return False
+
+
+class _DebugResult(object):
+    "Used by the TestSuite to hold previous class when running in debug."
+    _previousTestClass = None
+    _moduleSetUpFailed = False
+    shouldStop = False

Modified: python/branches/py3k/Lib/unittest/test/test_runner.py
==============================================================================
--- python/branches/py3k/Lib/unittest/test/test_runner.py	(original)
+++ python/branches/py3k/Lib/unittest/test/test_runner.py	Thu Jun 10 18:16:08 2010
@@ -110,6 +110,31 @@
         test.run(result)
         self.assertEqual(ordering, ['setUp', 'cleanup1'])
 
+    def testTestCaseDebugExecutesCleanups(self):
+        ordering = []
+
+        class TestableTest(unittest.TestCase):
+            def setUp(self):
+                ordering.append('setUp')
+                self.addCleanup(cleanup1)
+
+            def testNothing(self):
+                ordering.append('test')
+
+            def tearDown(self):
+                ordering.append('tearDown')
+
+        test = TestableTest('testNothing')
+
+        def cleanup1():
+            ordering.append('cleanup1')
+            test.addCleanup(cleanup2)
+        def cleanup2():
+            ordering.append('cleanup2')
+
+        test.debug()
+        self.assertEqual(ordering, ['setUp', 'test', 'tearDown', 'cleanup1', 'cleanup2'])
+
 
 class Test_TextTestRunner(unittest.TestCase):
     """Tests for TextTestRunner."""

Modified: python/branches/py3k/Lib/unittest/test/test_setups.py
==============================================================================
--- python/branches/py3k/Lib/unittest/test/test_setups.py	(original)
+++ python/branches/py3k/Lib/unittest/test/test_setups.py	Thu Jun 10 18:16:08 2010
@@ -438,6 +438,68 @@
         skipped = result.skipped[0][0]
         self.assertEqual(str(skipped), 'setUpModule (Module)')
 
+    def test_suite_debug_executes_setups_and_teardowns(self):
+        ordering = []
+
+        class Module(object):
+            @staticmethod
+            def setUpModule():
+                ordering.append('setUpModule')
+            @staticmethod
+            def tearDownModule():
+                ordering.append('tearDownModule')
+
+        class Test(unittest.TestCase):
+            @classmethod
+            def setUpClass(cls):
+                ordering.append('setUpClass')
+            @classmethod
+            def tearDownClass(cls):
+                ordering.append('tearDownClass')
+            def test_something(self):
+                ordering.append('test_something')
+
+        Test.__module__ = 'Module'
+        sys.modules['Module'] = Module
+
+        suite = unittest.defaultTestLoader.loadTestsFromTestCase(Test)
+        suite.debug()
+        expectedOrder = ['setUpModule', 'setUpClass', 'test_something', 'tearDownClass', 'tearDownModule']
+        self.assertEqual(ordering, expectedOrder)
+
+    def test_suite_debug_propagates_exceptions(self):
+        class Module(object):
+            @staticmethod
+            def setUpModule():
+                if phase == 0:
+                    raise Exception('setUpModule')
+            @staticmethod
+            def tearDownModule():
+                if phase == 1:
+                    raise Exception('tearDownModule')
+
+        class Test(unittest.TestCase):
+            @classmethod
+            def setUpClass(cls):
+                if phase == 2:
+                    raise Exception('setUpClass')
+            @classmethod
+            def tearDownClass(cls):
+                if phase == 3:
+                    raise Exception('tearDownClass')
+            def test_something(self):
+                if phase == 4:
+                    raise Exception('test_something')
+
+        Test.__module__ = 'Module'
+        sys.modules['Module'] = Module
+
+        suite = unittest.defaultTestLoader.loadTestsFromTestCase(Test)
+
+        messages = ('setUpModule', 'tearDownModule', 'setUpClass', 'tearDownClass', 'test_something')
+        for phase, msg in enumerate(messages):
+            with self.assertRaisesRegexp(Exception, msg):
+                suite.debug()
 
 if __name__ == '__main__':
     unittest.main()


More information about the Python-checkins mailing list