Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5acd41e

Browse files
committed
Merged revisions 67979 via svnmerge from
svn+ssh://[email protected]/python/trunk ........ r67979 | antoine.pitrou | 2008-12-28 15:09:36 +0100 (dim., 28 déc. 2008) | 3 lines Issue #4444: Allow assertRaises() to be used as a context handler. ........
1 parent ccc47b6 commit 5acd41e

4 files changed

Lines changed: 88 additions & 11 deletions

File tree

Doc/library/unittest.rst

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,15 +609,20 @@ failures.
609609
equal, the test will fail with the explanation given by *msg*, or :const:`None`.
610610

611611

612-
.. method:: TestCase.assertRaises(exception, callable, ...)
613-
TestCase.failUnlessRaises(exception, callable, ...)
612+
.. method:: TestCase.assertRaises(exception[, callable, ...])
613+
TestCase.failUnlessRaises(exception[, callable, ...])
614614

615615
Test that an exception is raised when *callable* is called with any positional
616616
or keyword arguments that are also passed to :meth:`assertRaises`. The test
617617
passes if *exception* is raised, is an error if another exception is raised, or
618618
fails if no exception is raised. To catch any of a group of exceptions, a tuple
619619
containing the exception classes may be passed as *exception*.
620620

621+
If *callable* is omitted or None, returns a context manager so that the code
622+
under test can be written inline rather than as a function::
623+
624+
with self.failUnlessRaises(some_error_class):
625+
do_something()
621626

622627
.. method:: TestCase.failIf(expr[, msg])
623628
TestCase.assertFalse(expr[, msg])

Lib/test/test_unittest.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,6 +2284,43 @@ def test_AlmostEqual(self):
22842284
self.assertRaises(AssertionError,
22852285
self.failIfAlmostEqual, 0, .1+.1j, places=0)
22862286

2287+
def test_assertRaises(self):
2288+
def _raise(e):
2289+
raise e
2290+
self.assertRaises(KeyError, _raise, KeyError)
2291+
self.assertRaises(KeyError, _raise, KeyError("key"))
2292+
try:
2293+
self.assertRaises(KeyError, lambda: None)
2294+
except AssertionError as e:
2295+
self.assert_("KeyError not raised" in str(e), str(e))
2296+
else:
2297+
self.fail("assertRaises() didn't fail")
2298+
try:
2299+
self.assertRaises(KeyError, _raise, ValueError)
2300+
except ValueError:
2301+
pass
2302+
else:
2303+
self.fail("assertRaises() didn't let exception pass through")
2304+
with self.assertRaises(KeyError):
2305+
raise KeyError
2306+
with self.assertRaises(KeyError):
2307+
raise KeyError("key")
2308+
try:
2309+
with self.assertRaises(KeyError):
2310+
pass
2311+
except AssertionError as e:
2312+
self.assert_("KeyError not raised" in str(e), str(e))
2313+
else:
2314+
self.fail("assertRaises() didn't fail")
2315+
try:
2316+
with self.assertRaises(KeyError):
2317+
raise ValueError
2318+
except ValueError:
2319+
pass
2320+
else:
2321+
self.fail("assertRaises() didn't let exception pass through")
2322+
2323+
22872324
######################################################################
22882325
## Main
22892326
######################################################################

Lib/unittest.py

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,36 @@ def __repr__(self):
149149
(_strclass(self.__class__), self.testsRun, len(self.errors),
150150
len(self.failures))
151151

152+
class AssertRaisesContext:
153+
def __init__(self, expected, test_case, callable_obj=None):
154+
self.expected = expected
155+
self.failureException = test_case.failureException
156+
if callable_obj is not None:
157+
try:
158+
self.obj_name = callable_obj.__name__
159+
except AttributeError:
160+
self.obj_name = str(callable_obj)
161+
else:
162+
self.obj_name = None
163+
def __enter__(self):
164+
pass
165+
def __exit__(self, exc_type, exc_value, traceback):
166+
if exc_type is None:
167+
try:
168+
exc_name = self.expected.__name__
169+
except AttributeError:
170+
exc_name = str(self.expected)
171+
if self.obj_name:
172+
raise self.failureException("{0} not raised by {1}"
173+
.format(exc_name, self.obj_name))
174+
else:
175+
raise self.failureException("{0} not raised"
176+
.format(exc_name))
177+
if issubclass(exc_type, self.expected):
178+
return True
179+
# Let unexpected exceptions skip through
180+
return False
181+
152182
class TestCase:
153183
"""A class whose instances are single test cases.
154184
@@ -299,23 +329,25 @@ def failUnless(self, expr, msg=None):
299329
"""Fail the test unless the expression is true."""
300330
if not expr: raise self.failureException(msg)
301331

302-
def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
332+
def failUnlessRaises(self, excClass, callableObj=None, *args, **kwargs):
303333
"""Fail unless an exception of class excClass is thrown
304334
by callableObj when invoked with arguments args and keyword
305335
arguments kwargs. If a different type of exception is
306336
thrown, it will not be caught, and the test case will be
307337
deemed to have suffered an error, exactly as for an
308338
unexpected exception.
339+
340+
If called with callableObj omitted or None, will return a
341+
context object used like this::
342+
343+
with self.failUnlessRaises(some_error_class):
344+
do_something()
309345
"""
310-
try:
346+
context = AssertRaisesContext(excClass, self, callableObj)
347+
if callableObj is None:
348+
return context
349+
with context:
311350
callableObj(*args, **kwargs)
312-
except excClass:
313-
return
314-
else:
315-
excName = str(getattr(excClass, '__name__', excClass))
316-
objName = str(getattr(callableObj, '__name__', callableObj))
317-
raise self.failureException("%s not raised by %s" % (excName,
318-
objName))
319351

320352
def failUnlessEqual(self, first, second, msg=None):
321353
"""Fail if the two objects are unequal as determined by the '=='

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ Core and Builtins
6464
Library
6565
-------
6666

67+
- Issue #4444: Allow assertRaises() to be used as a context handler, so that
68+
the code under test can be written inline if more practical.
69+
6770
- Issue #4756: zipfile.is_zipfile() now supports file-like objects. Patch by
6871
Gabriel Genellina.
6972

0 commit comments

Comments
 (0)