mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	Fix for potentials errors in constructing unittest failure messages. Plus skipped test methods no longer run setUp and tearDown (Issue 8059)
This commit is contained in:
		
							parent
							
								
									fc8a1ed70e
								
							
						
					
					
						commit
						53e8eeadd6
					
				
					 2 changed files with 70 additions and 13 deletions
				
			
		|  | @ -3118,6 +3118,43 @@ def test_die(self): | ||||||
|         self.assertEqual(result.unexpectedSuccesses, [test]) |         self.assertEqual(result.unexpectedSuccesses, [test]) | ||||||
|         self.assertTrue(result.wasSuccessful()) |         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): | class Test_Assertions(TestCase): | ||||||
|  | @ -3220,6 +3257,16 @@ def test_formatMsg(self): | ||||||
|         self.assertEquals(self.testableTrue._formatMessage(None, "foo"), "foo") |         self.assertEquals(self.testableTrue._formatMessage(None, "foo"), "foo") | ||||||
|         self.assertEquals(self.testableTrue._formatMessage("foo", "bar"), "bar : 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 assertMessages(self, methodName, args, errors): | ||||||
|         def getMethod(i): |         def getMethod(i): | ||||||
|             useTestableFalse  = i < 2 |             useTestableFalse  = i < 2 | ||||||
|  |  | ||||||
|  | @ -45,14 +45,15 @@ def skip(reason): | ||||||
|     Unconditionally skip a test. |     Unconditionally skip a test. | ||||||
|     """ |     """ | ||||||
|     def decorator(test_item): |     def decorator(test_item): | ||||||
|         if isinstance(test_item, type) and issubclass(test_item, TestCase): |         if not (isinstance(test_item, type) and issubclass(test_item, TestCase)): | ||||||
|             test_item.__unittest_skip__ = True |             @functools.wraps(test_item) | ||||||
|             test_item.__unittest_skip_why__ = reason |             def skip_wrapper(*args, **kwargs): | ||||||
|             return test_item |                 raise SkipTest(reason) | ||||||
|         @functools.wraps(test_item) |             test_item = skip_wrapper | ||||||
|         def skip_wrapper(*args, **kwargs): | 
 | ||||||
|             raise SkipTest(reason) |         test_item.__unittest_skip__ = True | ||||||
|         return skip_wrapper |         test_item.__unittest_skip_why__ = reason | ||||||
|  |         return test_item | ||||||
|     return decorator |     return decorator | ||||||
| 
 | 
 | ||||||
| def skipIf(condition, reason): | def skipIf(condition, reason): | ||||||
|  | @ -268,14 +269,18 @@ def run(self, result=None): | ||||||
| 
 | 
 | ||||||
|         self._resultForDoCleanups = result |         self._resultForDoCleanups = result | ||||||
|         result.startTest(self) |         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: |             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: |             finally: | ||||||
|                 result.stopTest(self) |                 result.stopTest(self) | ||||||
|             return |             return | ||||||
|         testMethod = getattr(self, self._testMethodName) |  | ||||||
|         try: |         try: | ||||||
|             success = False |             success = False | ||||||
|             try: |             try: | ||||||
|  | @ -386,7 +391,12 @@ def _formatMessage(self, msg, standardMsg): | ||||||
|             return msg or standardMsg |             return msg or standardMsg | ||||||
|         if msg is None: |         if msg is None: | ||||||
|             return standardMsg |             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): |     def assertRaises(self, excClass, callableObj=None, *args, **kwargs): | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Michael Foord
						Michael Foord