[Python-checkins] r78770 - in python/trunk/Lib: test/test_unittest.py unittest/case.py

michael.foord python-checkins at python.org
Sun Mar 7 21:22:12 CET 2010


Author: michael.foord
Date: Sun Mar  7 21:22:12 2010
New Revision: 78770

Log:
Fix for potentials errors in constructing unittest failure messages. Plus skipped test methods no longer run setUp and tearDown (Issue 8059)

Modified:
   python/trunk/Lib/test/test_unittest.py
   python/trunk/Lib/unittest/case.py

Modified: python/trunk/Lib/test/test_unittest.py
==============================================================================
--- python/trunk/Lib/test/test_unittest.py	(original)
+++ python/trunk/Lib/test/test_unittest.py	Sun Mar  7 21:22:12 2010
@@ -3118,6 +3118,43 @@
         self.assertEqual(result.unexpectedSuccesses, [test])
         self.assertTrue(result.wasSuccessful())
 
+    def test_skip_doesnt_run_setup(self):
+        class Foo(unittest.TestCase):
+            wasSetUp = False
+            wasTornDown = False
+            def setUp(self):
+                Foo.wasSetUp = True
+            def tornDown(self):
+                Foo.wasTornDown = True
+            @unittest.skip('testing')
+            def test_1(self):
+                pass
+
+        result = unittest.TestResult()
+        test = Foo("test_1")
+        suite = unittest.TestSuite([test])
+        suite.run(result)
+        self.assertEqual(result.skipped, [(test, "testing")])
+        self.assertFalse(Foo.wasSetUp)
+        self.assertFalse(Foo.wasTornDown)
+
+    def test_decorated_skip(self):
+        def decorator(func):
+            def inner(*a):
+                return func(*a)
+            return inner
+
+        class Foo(unittest.TestCase):
+            @decorator
+            @unittest.skip('testing')
+            def test_1(self):
+                pass
+
+        result = unittest.TestResult()
+        test = Foo("test_1")
+        suite = unittest.TestSuite([test])
+        suite.run(result)
+        self.assertEqual(result.skipped, [(test, "testing")])
 
 
 class Test_Assertions(TestCase):
@@ -3220,6 +3257,16 @@
         self.assertEquals(self.testableTrue._formatMessage(None, "foo"), "foo")
         self.assertEquals(self.testableTrue._formatMessage("foo", "bar"), "bar : foo")
 
+        # This blows up if _formatMessage uses string concatenation
+        self.testableTrue._formatMessage(object(), 'foo')
+
+    def test_formatMessage_unicode_error(self):
+        with warnings.catch_warnings(record=True):
+            # This causes a UnicodeWarning due to its craziness
+            one = ''.join(chr(i) for i in range(255))
+            # this used to cause a UnicodeDecodeError constructing msg
+            self.testableTrue._formatMessage(one, u'\uFFFD')
+
     def assertMessages(self, methodName, args, errors):
         def getMethod(i):
             useTestableFalse  = i < 2

Modified: python/trunk/Lib/unittest/case.py
==============================================================================
--- python/trunk/Lib/unittest/case.py	(original)
+++ python/trunk/Lib/unittest/case.py	Sun Mar  7 21:22:12 2010
@@ -45,14 +45,15 @@
     Unconditionally skip a test.
     """
     def decorator(test_item):
-        if isinstance(test_item, type) and issubclass(test_item, TestCase):
-            test_item.__unittest_skip__ = True
-            test_item.__unittest_skip_why__ = reason
-            return test_item
-        @functools.wraps(test_item)
-        def skip_wrapper(*args, **kwargs):
-            raise SkipTest(reason)
-        return skip_wrapper
+        if not (isinstance(test_item, type) and issubclass(test_item, TestCase)):
+            @functools.wraps(test_item)
+            def skip_wrapper(*args, **kwargs):
+                raise SkipTest(reason)
+            test_item = skip_wrapper
+
+        test_item.__unittest_skip__ = True
+        test_item.__unittest_skip_why__ = reason
+        return test_item
     return decorator
 
 def skipIf(condition, reason):
@@ -268,14 +269,18 @@
 
         self._resultForDoCleanups = result
         result.startTest(self)
-        if getattr(self.__class__, "__unittest_skip__", False):
-            # If the whole class was skipped.
+
+        testMethod = getattr(self, self._testMethodName)
+        if (getattr(self.__class__, "__unittest_skip__", False) or
+            getattr(testMethod, "__unittest_skip__", False)):
+            # If the class or method was skipped.
             try:
-                self._addSkip(result, self.__class__.__unittest_skip_why__)
+                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
+                            or getattr(testMethod, '__unittest_skip_why__', ''))
+                self._addSkip(result, skip_why)
             finally:
                 result.stopTest(self)
             return
-        testMethod = getattr(self, self._testMethodName)
         try:
             success = False
             try:
@@ -386,7 +391,12 @@
             return msg or standardMsg
         if msg is None:
             return standardMsg
-        return standardMsg + ' : ' + msg
+        try:
+            # don't switch to '{}' formatting in Python 2.X
+            # it changes the way unicode input is handled
+            return '%s : %s' % (standardMsg, msg)
+        except UnicodeDecodeError:
+            return  '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
 
 
     def assertRaises(self, excClass, callableObj=None, *args, **kwargs):


More information about the Python-checkins mailing list