Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and

assertWarnsRegex() checks are not longer successful if the callable is None.

Added tests for assertRaises().
This commit is contained in:
Serhiy Storchaka 2015-05-06 19:14:47 +03:00
commit 24d3b7f9df
3 changed files with 68 additions and 11 deletions

View File

@ -129,15 +129,17 @@ class _BaseTestCaseContext:
msg = self.test_case._formatMessage(self.msg, standardMsg) msg = self.test_case._formatMessage(self.msg, standardMsg)
raise self.test_case.failureException(msg) raise self.test_case.failureException(msg)
def _sentinel(*args, **kwargs):
raise AssertionError('Should never called')
class _AssertRaisesBaseContext(_BaseTestCaseContext): class _AssertRaisesBaseContext(_BaseTestCaseContext):
def __init__(self, expected, test_case, callable_obj=None, def __init__(self, expected, test_case, callable_obj=_sentinel,
expected_regex=None): expected_regex=None):
_BaseTestCaseContext.__init__(self, test_case) _BaseTestCaseContext.__init__(self, test_case)
self.expected = expected self.expected = expected
self.test_case = test_case self.test_case = test_case
if callable_obj is not None: if callable_obj is not _sentinel:
try: try:
self.obj_name = callable_obj.__name__ self.obj_name = callable_obj.__name__
except AttributeError: except AttributeError:
@ -151,11 +153,11 @@ class _AssertRaisesBaseContext(_BaseTestCaseContext):
def handle(self, name, callable_obj, args, kwargs): def handle(self, name, callable_obj, args, kwargs):
""" """
If callable_obj is None, assertRaises/Warns is being used as a If callable_obj is _sentinel, assertRaises/Warns is being used as a
context manager, so check for a 'msg' kwarg and return self. context manager, so check for a 'msg' kwarg and return self.
If callable_obj is not None, call it passing args and kwargs. If callable_obj is not _sentinel, call it passing args and kwargs.
""" """
if callable_obj is None: if callable_obj is _sentinel:
self.msg = kwargs.pop('msg', None) self.msg = kwargs.pop('msg', None)
return self return self
with self: with self:
@ -674,7 +676,7 @@ class TestCase(object):
except UnicodeDecodeError: except UnicodeDecodeError:
return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg)) 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 """Fail unless an exception of class excClass is raised
by callableObj when invoked with arguments args and keyword by callableObj when invoked with arguments args and keyword
arguments kwargs. If a different type of exception is arguments kwargs. If a different type of exception is
@ -682,7 +684,7 @@ class TestCase(object):
deemed to have suffered an error, exactly as for an deemed to have suffered an error, exactly as for an
unexpected exception. 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:: context object used like this::
with self.assertRaises(SomeException): with self.assertRaises(SomeException):
@ -703,7 +705,7 @@ class TestCase(object):
context = _AssertRaisesContext(excClass, self, callableObj) context = _AssertRaisesContext(excClass, self, callableObj)
return context.handle('assertRaises', callableObj, args, kwargs) return context.handle('assertRaises', callableObj, args, kwargs)
def assertWarns(self, expected_warning, callable_obj=None, *args, **kwargs): def assertWarns(self, expected_warning, callable_obj=_sentinel, *args, **kwargs):
"""Fail unless a warning of class warnClass is triggered """Fail unless a warning of class warnClass is triggered
by callable_obj when invoked with arguments args and keyword by callable_obj when invoked with arguments args and keyword
arguments kwargs. If a different type of warning is arguments kwargs. If a different type of warning is
@ -711,7 +713,7 @@ class TestCase(object):
warning filtering rules in effect, it might be silenced, printed warning filtering rules in effect, it might be silenced, printed
out, or raised as an exception. out, or raised as an exception.
If called with callable_obj omitted or None, will return a If called with callable_obj omitted, will return a
context object used like this:: context object used like this::
with self.assertWarns(SomeWarning): with self.assertWarns(SomeWarning):
@ -1219,7 +1221,7 @@ class TestCase(object):
self.fail(self._formatMessage(msg, standardMsg)) self.fail(self._formatMessage(msg, standardMsg))
def assertRaisesRegex(self, expected_exception, expected_regex, def assertRaisesRegex(self, expected_exception, expected_regex,
callable_obj=None, *args, **kwargs): callable_obj=_sentinel, *args, **kwargs):
"""Asserts that the message in a raised exception matches a regex. """Asserts that the message in a raised exception matches a regex.
Args: Args:
@ -1238,7 +1240,7 @@ class TestCase(object):
return context.handle('assertRaisesRegex', callable_obj, args, kwargs) return context.handle('assertRaisesRegex', callable_obj, args, kwargs)
def assertWarnsRegex(self, expected_warning, expected_regex, def assertWarnsRegex(self, expected_warning, expected_regex,
callable_obj=None, *args, **kwargs): callable_obj=_sentinel, *args, **kwargs):
"""Asserts that the message in a triggered warning matches a regexp. """Asserts that the message in a triggered warning matches a regexp.
Basic functioning is similar to assertWarns() with the addition Basic functioning is similar to assertWarns() with the addition
that only warnings whose messages also match the regular expression that only warnings whose messages also match the regular expression

View File

@ -1132,6 +1132,50 @@ test case
self.assertRaises(self.failureException, self.assertRegex, self.assertRaises(self.failureException, self.assertRegex,
'saaas', r'aaaa') '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 testAssertRaisesRegex(self): def testAssertRaisesRegex(self):
class ExceptionMock(Exception): class ExceptionMock(Exception):
pass pass
@ -1141,6 +1185,8 @@ test case
self.assertRaisesRegex(ExceptionMock, re.compile('expect$'), Stub) self.assertRaisesRegex(ExceptionMock, re.compile('expect$'), Stub)
self.assertRaisesRegex(ExceptionMock, 'expect$', Stub) self.assertRaisesRegex(ExceptionMock, 'expect$', Stub)
with self.assertRaises(TypeError):
self.assertRaisesRegex(ExceptionMock, 'expect$', None)
def testAssertNotRaisesRegex(self): def testAssertNotRaisesRegex(self):
self.assertRaisesRegex( self.assertRaisesRegex(
@ -1208,6 +1254,9 @@ test case
# Failure when no warning is triggered # Failure when no warning is triggered
with self.assertRaises(self.failureException): with self.assertRaises(self.failureException):
self.assertWarns(RuntimeWarning, lambda: 0) self.assertWarns(RuntimeWarning, lambda: 0)
# Failure when the function is None
with self.assertRaises(TypeError):
self.assertWarns(RuntimeWarning, None)
# Failure when another warning is triggered # Failure when another warning is triggered
with warnings.catch_warnings(): with warnings.catch_warnings():
# Force default filter (in case tests are run with -We) # Force default filter (in case tests are run with -We)
@ -1269,6 +1318,9 @@ test case
with self.assertRaises(self.failureException): with self.assertRaises(self.failureException):
self.assertWarnsRegex(RuntimeWarning, "o+", self.assertWarnsRegex(RuntimeWarning, "o+",
lambda: 0) lambda: 0)
# Failure when the function is None
with self.assertRaises(TypeError):
self.assertWarnsRegex(RuntimeWarning, "o+", None)
# Failure when another warning is triggered # Failure when another warning is triggered
with warnings.catch_warnings(): with warnings.catch_warnings():
# Force default filter (in case tests are run with -We) # Force default filter (in case tests are run with -We)

View File

@ -30,6 +30,9 @@ Core and Builtins
Library Library
------- -------
- Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and
assertWarnsRegex() checks are not longer successful if the callable is None.
- Issue #23880: Tkinter's getint() and getdouble() now support Tcl_Obj. - Issue #23880: Tkinter's getint() and getdouble() now support Tcl_Obj.
Tkinter's getdouble() now supports any numbers (in particular int). Tkinter's getdouble() now supports any numbers (in particular int).