mirror of
https://github.com/python/cpython.git
synced 2025-11-24 20:30:18 +00:00
Issue #4444: Allow assertRaises() to be used as a context handler.
This commit is contained in:
parent
40f982fbdf
commit
697ca3d0cb
4 changed files with 79 additions and 10 deletions
|
|
@ -613,8 +613,8 @@ failures.
|
||||||
equal, the test will fail with the explanation given by *msg*, or :const:`None`.
|
equal, the test will fail with the explanation given by *msg*, or :const:`None`.
|
||||||
|
|
||||||
|
|
||||||
.. method:: TestCase.assertRaises(exception, callable, ...)
|
.. method:: TestCase.assertRaises(exception[, callable, ...])
|
||||||
TestCase.failUnlessRaises(exception, callable, ...)
|
TestCase.failUnlessRaises(exception[, callable, ...])
|
||||||
|
|
||||||
Test that an exception is raised when *callable* is called with any positional
|
Test that an exception is raised when *callable* is called with any positional
|
||||||
or keyword arguments that are also passed to :meth:`assertRaises`. The test
|
or keyword arguments that are also passed to :meth:`assertRaises`. The test
|
||||||
|
|
@ -622,6 +622,13 @@ failures.
|
||||||
fails if no exception is raised. To catch any of a group of exceptions, a tuple
|
fails if no exception is raised. To catch any of a group of exceptions, a tuple
|
||||||
containing the exception classes may be passed as *exception*.
|
containing the exception classes may be passed as *exception*.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.2
|
||||||
|
|
||||||
|
If *callable* is omitted or None, returns a context manager so that the code
|
||||||
|
under test can be written inline rather than as a function::
|
||||||
|
|
||||||
|
with self.failUnlessRaises(some_error_class):
|
||||||
|
do_something()
|
||||||
|
|
||||||
.. method:: TestCase.failIf(expr[, msg])
|
.. method:: TestCase.failIf(expr[, msg])
|
||||||
TestCase.assertFalse(expr[, msg])
|
TestCase.assertFalse(expr[, msg])
|
||||||
|
|
|
||||||
|
|
@ -2284,6 +2284,43 @@ class Test_Assertions(TestCase):
|
||||||
self.assertRaises(AssertionError,
|
self.assertRaises(AssertionError,
|
||||||
self.failIfAlmostEqual, 0, .1+.1j, places=0)
|
self.failIfAlmostEqual, 0, .1+.1j, places=0)
|
||||||
|
|
||||||
|
def test_assertRaises(self):
|
||||||
|
def _raise(e):
|
||||||
|
raise e
|
||||||
|
self.assertRaises(KeyError, _raise, KeyError)
|
||||||
|
self.assertRaises(KeyError, _raise, KeyError("key"))
|
||||||
|
try:
|
||||||
|
self.assertRaises(KeyError, lambda: None)
|
||||||
|
except AssertionError as e:
|
||||||
|
self.assert_("KeyError not raised" in e, str(e))
|
||||||
|
else:
|
||||||
|
self.fail("assertRaises() didn't fail")
|
||||||
|
try:
|
||||||
|
self.assertRaises(KeyError, _raise, ValueError)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.fail("assertRaises() didn't let exception pass through")
|
||||||
|
with self.assertRaises(KeyError):
|
||||||
|
raise KeyError
|
||||||
|
with self.assertRaises(KeyError):
|
||||||
|
raise KeyError("key")
|
||||||
|
try:
|
||||||
|
with self.assertRaises(KeyError):
|
||||||
|
pass
|
||||||
|
except AssertionError as e:
|
||||||
|
self.assert_("KeyError not raised" in e, str(e))
|
||||||
|
else:
|
||||||
|
self.fail("assertRaises() didn't fail")
|
||||||
|
try:
|
||||||
|
with self.assertRaises(KeyError):
|
||||||
|
raise ValueError
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.fail("assertRaises() didn't let exception pass through")
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
## Main
|
## Main
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,25 @@ class TestResult:
|
||||||
(_strclass(self.__class__), self.testsRun, len(self.errors),
|
(_strclass(self.__class__), self.testsRun, len(self.errors),
|
||||||
len(self.failures))
|
len(self.failures))
|
||||||
|
|
||||||
|
class AssertRaisesContext:
|
||||||
|
def __init__(self, expected, test_case):
|
||||||
|
self.expected = expected
|
||||||
|
self.failureException = test_case.failureException
|
||||||
|
def __enter__(self):
|
||||||
|
pass
|
||||||
|
def __exit__(self, exc_type, exc_value, traceback):
|
||||||
|
if exc_type is None:
|
||||||
|
try:
|
||||||
|
exc_name = self.expected.__name__
|
||||||
|
except AttributeError:
|
||||||
|
exc_name = str(self.expected)
|
||||||
|
raise self.failureException(
|
||||||
|
"{0} not raised".format(exc_name))
|
||||||
|
if issubclass(exc_type, self.expected):
|
||||||
|
return True
|
||||||
|
# Let unexpected exceptions skip through
|
||||||
|
return False
|
||||||
|
|
||||||
class TestCase:
|
class TestCase:
|
||||||
"""A class whose instances are single test cases.
|
"""A class whose instances are single test cases.
|
||||||
|
|
||||||
|
|
@ -324,22 +343,25 @@ class TestCase:
|
||||||
"""Fail the test unless the expression is true."""
|
"""Fail the test unless the expression is true."""
|
||||||
if not expr: raise self.failureException, msg
|
if not expr: raise self.failureException, msg
|
||||||
|
|
||||||
def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
|
def failUnlessRaises(self, excClass, callableObj=None, *args, **kwargs):
|
||||||
"""Fail unless an exception of class excClass is thrown
|
"""Fail unless an exception of class excClass is thrown
|
||||||
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
|
||||||
thrown, it will not be caught, and the test case will be
|
thrown, it will not be caught, and the test case will be
|
||||||
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
|
||||||
|
context object used like this::
|
||||||
|
|
||||||
|
with self.failUnlessRaises(some_error_class):
|
||||||
|
do_something()
|
||||||
"""
|
"""
|
||||||
try:
|
context = AssertRaisesContext(excClass, self)
|
||||||
|
if callableObj is None:
|
||||||
|
return context
|
||||||
|
with context:
|
||||||
callableObj(*args, **kwargs)
|
callableObj(*args, **kwargs)
|
||||||
except excClass:
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
if hasattr(excClass,'__name__'): excName = excClass.__name__
|
|
||||||
else: excName = str(excClass)
|
|
||||||
raise self.failureException, "%s not raised" % excName
|
|
||||||
|
|
||||||
def failUnlessEqual(self, first, second, msg=None):
|
def failUnlessEqual(self, first, second, msg=None):
|
||||||
"""Fail if the two objects are unequal as determined by the '=='
|
"""Fail if the two objects are unequal as determined by the '=='
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #4444: Allow assertRaises() to be used as a context handler, so that
|
||||||
|
the code under test can be written inline if more practical.
|
||||||
|
|
||||||
- Issue #4739: Add pydoc help topics for symbols, so that e.g. help('@')
|
- Issue #4739: Add pydoc help topics for symbols, so that e.g. help('@')
|
||||||
works as expected in the interactive environment.
|
works as expected in the interactive environment.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue