summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2015-05-16 13:29:50 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2015-05-16 13:29:50 (GMT)
commitdf573d6ad81d61d75060eec71558ed50fa4aacf2 (patch)
treefbb33a12ffe4fc1ffae5aebe1652a5c4bdd735b0
parent6b680cd6b2a0ecc8d5e6fe671e2eda6608c53a85 (diff)
downloadcpython-df573d6ad81d61d75060eec71558ed50fa4aacf2.zip
cpython-df573d6ad81d61d75060eec71558ed50fa4aacf2.tar.gz
cpython-df573d6ad81d61d75060eec71558ed50fa4aacf2.tar.bz2
Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and
assertWarnsRegex() checks now emits a deprecation warning when callable is None or keyword arguments except msg is passed in the context manager mode.
-rw-r--r--Lib/unittest/case.py88
-rw-r--r--Lib/unittest/test/test_case.py44
-rw-r--r--Misc/NEWS3
3 files changed, 86 insertions, 49 deletions
diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py
index 225a143..befad61 100644
--- a/Lib/unittest/case.py
+++ b/Lib/unittest/case.py
@@ -129,37 +129,42 @@ class _BaseTestCaseContext:
msg = self.test_case._formatMessage(self.msg, standardMsg)
raise self.test_case.failureException(msg)
-def _sentinel(*args, **kwargs):
- raise AssertionError('Should never be called')
-
class _AssertRaisesBaseContext(_BaseTestCaseContext):
- def __init__(self, expected, test_case, callable_obj=_sentinel,
- expected_regex=None):
+ def __init__(self, expected, test_case, expected_regex=None):
_BaseTestCaseContext.__init__(self, test_case)
self.expected = expected
self.test_case = test_case
- if callable_obj is not _sentinel:
- try:
- self.obj_name = callable_obj.__name__
- except AttributeError:
- self.obj_name = str(callable_obj)
- else:
- self.obj_name = None
if expected_regex is not None:
expected_regex = re.compile(expected_regex)
self.expected_regex = expected_regex
+ self.obj_name = None
self.msg = None
- def handle(self, name, callable_obj, args, kwargs):
+ def handle(self, name, args, kwargs):
"""
- If callable_obj is _sentinel, assertRaises/Warns is being used as a
+ If args is empty, assertRaises/Warns is being used as a
context manager, so check for a 'msg' kwarg and return self.
- If callable_obj is not _sentinel, call it passing args and kwargs.
+ If args is not empty, call a callable passing positional and keyword
+ arguments.
"""
- if callable_obj is _sentinel:
+ if args and args[0] is None:
+ warnings.warn("callable is None",
+ DeprecationWarning, 3)
+ args = ()
+ if not args:
self.msg = kwargs.pop('msg', None)
+ if kwargs:
+ warnings.warn('%r is an invalid keyword argument for '
+ 'this function' % next(iter(kwargs)),
+ DeprecationWarning, 3)
return self
+
+ callable_obj, *args = args
+ try:
+ self.obj_name = callable_obj.__name__
+ except AttributeError:
+ self.obj_name = str(callable_obj)
with self:
callable_obj(*args, **kwargs)
@@ -676,15 +681,15 @@ class TestCase(object):
except UnicodeDecodeError:
return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
- 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
+ def assertRaises(self, expected_exception, *args, **kwargs):
+ """Fail unless an exception of class expected_exception is raised
+ by the callable when invoked with specified positional and
+ keyword arguments. If a different type of exception is
raised, it will not be caught, and the test case will be
deemed to have suffered an error, exactly as for an
unexpected exception.
- If called with callableObj omitted, will return a
+ If called with the callable and arguments omitted, will return a
context object used like this::
with self.assertRaises(SomeException):
@@ -702,18 +707,18 @@ class TestCase(object):
the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)
"""
- context = _AssertRaisesContext(excClass, self, callableObj)
- return context.handle('assertRaises', callableObj, args, kwargs)
+ context = _AssertRaisesContext(expected_exception, self)
+ return context.handle('assertRaises', args, kwargs)
- def assertWarns(self, expected_warning, callable_obj=_sentinel, *args, **kwargs):
+ def assertWarns(self, expected_warning, *args, **kwargs):
"""Fail unless a warning of class warnClass is triggered
- by callable_obj when invoked with arguments args and keyword
- arguments kwargs. If a different type of warning is
+ by the callable when invoked with specified positional and
+ keyword arguments. If a different type of warning is
triggered, it will not be handled: depending on the other
warning filtering rules in effect, it might be silenced, printed
out, or raised as an exception.
- If called with callable_obj omitted, will return a
+ If called with the callable and arguments omitted, will return a
context object used like this::
with self.assertWarns(SomeWarning):
@@ -733,8 +738,8 @@ class TestCase(object):
the_warning = cm.warning
self.assertEqual(the_warning.some_attribute, 147)
"""
- context = _AssertWarnsContext(expected_warning, self, callable_obj)
- return context.handle('assertWarns', callable_obj, args, kwargs)
+ context = _AssertWarnsContext(expected_warning, self)
+ return context.handle('assertWarns', args, kwargs)
def assertLogs(self, logger=None, level=None):
"""Fail unless a log message of level *level* or higher is emitted
@@ -1221,26 +1226,23 @@ class TestCase(object):
self.fail(self._formatMessage(msg, standardMsg))
def assertRaisesRegex(self, expected_exception, expected_regex,
- callable_obj=_sentinel, *args, **kwargs):
+ *args, **kwargs):
"""Asserts that the message in a raised exception matches a regex.
Args:
expected_exception: Exception class expected to be raised.
expected_regex: Regex (re pattern object or string) expected
to be found in error message.
- callable_obj: Function to be called.
+ args: Function to be called and extra positional args.
+ kwargs: Extra kwargs.
msg: Optional message used in case of failure. Can only be used
when assertRaisesRegex is used as a context manager.
- args: Extra args.
- kwargs: Extra kwargs.
"""
- context = _AssertRaisesContext(expected_exception, self, callable_obj,
- expected_regex)
-
- return context.handle('assertRaisesRegex', callable_obj, args, kwargs)
+ context = _AssertRaisesContext(expected_exception, self, expected_regex)
+ return context.handle('assertRaisesRegex', args, kwargs)
def assertWarnsRegex(self, expected_warning, expected_regex,
- callable_obj=_sentinel, *args, **kwargs):
+ *args, **kwargs):
"""Asserts that the message in a triggered warning matches a regexp.
Basic functioning is similar to assertWarns() with the addition
that only warnings whose messages also match the regular expression
@@ -1250,15 +1252,13 @@ class TestCase(object):
expected_warning: Warning class expected to be triggered.
expected_regex: Regex (re pattern object or string) expected
to be found in error message.
- callable_obj: Function to be called.
+ args: Function to be called and extra positional args.
+ kwargs: Extra kwargs.
msg: Optional message used in case of failure. Can only be used
when assertWarnsRegex is used as a context manager.
- args: Extra args.
- kwargs: Extra kwargs.
"""
- context = _AssertWarnsContext(expected_warning, self, callable_obj,
- expected_regex)
- return context.handle('assertWarnsRegex', callable_obj, args, kwargs)
+ context = _AssertWarnsContext(expected_warning, self, expected_regex)
+ return context.handle('assertWarnsRegex', args, kwargs)
def assertRegex(self, text, expected_regex, msg=None):
"""Fail the test unless the text matches the regular expression."""
diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py
index 75bb0d6..a05cc64 100644
--- a/Lib/unittest/test/test_case.py
+++ b/Lib/unittest/test/test_case.py
@@ -1146,7 +1146,7 @@ test case
with self.assertRaises(self.failureException):
self.assertRaises(ExceptionMock, lambda: 0)
# Failure when the function is None
- with self.assertRaises(TypeError):
+ with self.assertWarns(DeprecationWarning):
self.assertRaises(ExceptionMock, None)
# Failure when another exception is raised
with self.assertRaises(ExceptionMock):
@@ -1172,6 +1172,15 @@ test case
with self.assertRaises(self.failureException):
with self.assertRaises(ExceptionMock):
pass
+ # Custom message
+ with self.assertRaisesRegex(self.failureException, 'foobar'):
+ with self.assertRaises(ExceptionMock, msg='foobar'):
+ pass
+ # Invalid keyword argument
+ with self.assertWarnsRegex(DeprecationWarning, 'foobar'), \
+ self.assertRaises(AssertionError):
+ with self.assertRaises(ExceptionMock, foobar=42):
+ pass
# Failure when another exception is raised
with self.assertRaises(ExceptionMock):
self.assertRaises(ValueError, Stub)
@@ -1185,7 +1194,7 @@ test case
self.assertRaisesRegex(ExceptionMock, re.compile('expect$'), Stub)
self.assertRaisesRegex(ExceptionMock, 'expect$', Stub)
- with self.assertRaises(TypeError):
+ with self.assertWarns(DeprecationWarning):
self.assertRaisesRegex(ExceptionMock, 'expect$', None)
def testAssertNotRaisesRegex(self):
@@ -1197,6 +1206,15 @@ test case
self.failureException, '^Exception not raised by <lambda>$',
self.assertRaisesRegex, Exception, 'x',
lambda: None)
+ # Custom message
+ with self.assertRaisesRegex(self.failureException, 'foobar'):
+ with self.assertRaisesRegex(Exception, 'expect', msg='foobar'):
+ pass
+ # Invalid keyword argument
+ with self.assertWarnsRegex(DeprecationWarning, 'foobar'), \
+ self.assertRaises(AssertionError):
+ with self.assertRaisesRegex(Exception, 'expect', foobar=42):
+ pass
def testAssertRaisesRegexInvalidRegex(self):
# Issue 20145.
@@ -1255,7 +1273,7 @@ test case
with self.assertRaises(self.failureException):
self.assertWarns(RuntimeWarning, lambda: 0)
# Failure when the function is None
- with self.assertRaises(TypeError):
+ with self.assertWarns(DeprecationWarning):
self.assertWarns(RuntimeWarning, None)
# Failure when another warning is triggered
with warnings.catch_warnings():
@@ -1295,6 +1313,15 @@ test case
with self.assertRaises(self.failureException):
with self.assertWarns(RuntimeWarning):
pass
+ # Custom message
+ with self.assertRaisesRegex(self.failureException, 'foobar'):
+ with self.assertWarns(RuntimeWarning, msg='foobar'):
+ pass
+ # Invalid keyword argument
+ with self.assertWarnsRegex(DeprecationWarning, 'foobar'), \
+ self.assertRaises(AssertionError):
+ with self.assertWarns(RuntimeWarning, foobar=42):
+ pass
# Failure when another warning is triggered
with warnings.catch_warnings():
# Force default filter (in case tests are run with -We)
@@ -1319,7 +1346,7 @@ test case
self.assertWarnsRegex(RuntimeWarning, "o+",
lambda: 0)
# Failure when the function is None
- with self.assertRaises(TypeError):
+ with self.assertWarns(DeprecationWarning):
self.assertWarnsRegex(RuntimeWarning, "o+", None)
# Failure when another warning is triggered
with warnings.catch_warnings():
@@ -1357,6 +1384,15 @@ test case
with self.assertRaises(self.failureException):
with self.assertWarnsRegex(RuntimeWarning, "o+"):
pass
+ # Custom message
+ with self.assertRaisesRegex(self.failureException, 'foobar'):
+ with self.assertWarnsRegex(RuntimeWarning, 'o+', msg='foobar'):
+ pass
+ # Invalid keyword argument
+ with self.assertWarnsRegex(DeprecationWarning, 'foobar'), \
+ self.assertRaises(AssertionError):
+ with self.assertWarnsRegex(RuntimeWarning, 'o+', foobar=42):
+ pass
# Failure when another warning is triggered
with warnings.catch_warnings():
# Force default filter (in case tests are run with -We)
diff --git a/Misc/NEWS b/Misc/NEWS
index 5e8ba22..502d80f87 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -76,7 +76,8 @@ Library
usernames and passwords to UTF8.
- Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and
- assertWarnsRegex() checks are not longer successful if the callable is None.
+ assertWarnsRegex() checks now emits a deprecation warning when callable is
+ None or keyword arguments except msg is passed in the context manager mode.
- Issue #24018: Add a collections.abc.Generator abstract base class.
Contributed by Stefan Behnel.