changeset: 95897:111ec3d5bf19 branch: 2.7 parent: 95891:fe340c2a220e user: Serhiy Storchaka date: Wed May 06 19:10:40 2015 +0300 files: Lib/unittest/case.py Lib/unittest/test/test_case.py Misc/NEWS description: Issue #24134: assertRaises() and assertRaisesRegexp() checks are not longer successful if the callable is None. Added tests for assertRaises(). diff -r fe340c2a220e -r 111ec3d5bf19 Lib/unittest/case.py --- a/Lib/unittest/case.py Wed May 06 09:35:52 2015 +0300 +++ b/Lib/unittest/case.py Wed May 06 19:10:40 2015 +0300 @@ -127,6 +127,8 @@ (expected_regexp.pattern, str(exc_value))) return True +def _sentinel(*args, **kwargs): + raise AssertionError('Should never called') class TestCase(object): """A class whose instances are single test cases. @@ -443,7 +445,7 @@ return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg)) - def assertRaises(self, excClass, callableObj=None, *args, **kwargs): + def assertRaises(self, excClass, callableObj=_sentinel, *args, **kwargs): """Fail unless an exception of class excClass is raised by callableObj when invoked with arguments args and keyword arguments kwargs. If a different type of exception is @@ -451,7 +453,7 @@ deemed to have suffered an error, exactly as for an unexpected exception. - If called with callableObj omitted or None, will return a + If called with callableObj omitted, will return a context object used like this:: with self.assertRaises(SomeException): @@ -467,7 +469,7 @@ self.assertEqual(the_exception.error_code, 3) """ context = _AssertRaisesContext(excClass, self) - if callableObj is None: + if callableObj is _sentinel: return context with context: callableObj(*args, **kwargs) @@ -973,7 +975,7 @@ self.fail(self._formatMessage(msg, standardMsg)) def assertRaisesRegexp(self, expected_exception, expected_regexp, - callable_obj=None, *args, **kwargs): + callable_obj=_sentinel, *args, **kwargs): """Asserts that the message in a raised exception matches a regexp. Args: @@ -987,7 +989,7 @@ if expected_regexp is not None: expected_regexp = re.compile(expected_regexp) context = _AssertRaisesContext(expected_exception, self, expected_regexp) - if callable_obj is None: + if callable_obj is _sentinel: return context with context: callable_obj(*args, **kwargs) diff -r fe340c2a220e -r 111ec3d5bf19 Lib/unittest/test/test_case.py --- a/Lib/unittest/test/test_case.py Wed May 06 09:35:52 2015 +0300 +++ b/Lib/unittest/test/test_case.py Wed May 06 19:10:40 2015 +0300 @@ -954,6 +954,50 @@ self.assertRaises(self.failureException, self.assertRegexpMatches, 'saaas', r'aaaa') + def testAssertRaisesCallable(self): + class ExceptionMock(Exception): + pass + def Stub(): + raise ExceptionMock('We expect') + self.assertRaises(ExceptionMock, Stub) + # A tuple of exception classes is accepted + self.assertRaises((ValueError, ExceptionMock), Stub) + # *args and **kwargs also work + self.assertRaises(ValueError, int, '19', base=8) + # Failure when no exception is raised + with self.assertRaises(self.failureException): + self.assertRaises(ExceptionMock, lambda: 0) + # Failure when the function is None + with self.assertRaises(TypeError): + self.assertRaises(ExceptionMock, None) + # Failure when another exception is raised + with self.assertRaises(ExceptionMock): + self.assertRaises(ValueError, Stub) + + def testAssertRaisesContext(self): + class ExceptionMock(Exception): + pass + def Stub(): + raise ExceptionMock('We expect') + with self.assertRaises(ExceptionMock): + Stub() + # A tuple of exception classes is accepted + with self.assertRaises((ValueError, ExceptionMock)) as cm: + Stub() + # The context manager exposes caught exception + self.assertIsInstance(cm.exception, ExceptionMock) + self.assertEqual(cm.exception.args[0], 'We expect') + # *args and **kwargs also work + with self.assertRaises(ValueError): + int('19', base=8) + # Failure when no exception is raised + with self.assertRaises(self.failureException): + with self.assertRaises(ExceptionMock): + pass + # Failure when another exception is raised + with self.assertRaises(ExceptionMock): + self.assertRaises(ValueError, Stub) + def testAssertRaisesRegexp(self): class ExceptionMock(Exception): pass @@ -964,6 +1008,8 @@ self.assertRaisesRegexp(ExceptionMock, re.compile('expect$'), Stub) self.assertRaisesRegexp(ExceptionMock, 'expect$', Stub) self.assertRaisesRegexp(ExceptionMock, u'expect$', Stub) + with self.assertRaises(TypeError): + self.assertRaisesRegexp(ExceptionMock, 'expect$', None) def testAssertNotRaisesRegexp(self): self.assertRaisesRegexp( diff -r fe340c2a220e -r 111ec3d5bf19 Misc/NEWS --- a/Misc/NEWS Wed May 06 09:35:52 2015 +0300 +++ b/Misc/NEWS Wed May 06 19:10:40 2015 +0300 @@ -21,6 +21,9 @@ Library ------- +- Issue #24134: assertRaises() and assertRaisesRegexp() checks are not longer + successful if the callable is None. + - Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. - Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup