Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(31550)

Delta Between Two Patch Sets: Lib/unittest/case.py

Issue 15836: unittest assertRaises should verify excClass is actually a BaseException class
Left Patch Set: Created 7 years ago
Right Patch Set: Created 4 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Lib/test/test_importlib/builtin/test_loader.py ('k') | Lib/unittest/test/test_case.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 """Test case implementation""" 1 """Test case implementation"""
2 2
3 import sys 3 import sys
4 import functools 4 import functools
5 import difflib 5 import difflib
6 import logging
6 import pprint 7 import pprint
7 import re 8 import re
8 import warnings 9 import warnings
9 import collections 10 import collections
11 import contextlib
12 import traceback
10 13
11 from . import result 14 from . import result
12 from .util import (strclass, safe_repr, _count_diff_all_purpose, 15 from .util import (strclass, safe_repr, _count_diff_all_purpose,
13 _count_diff_hashable) 16 _count_diff_hashable, _common_shorten_repr)
14 17
15 __unittest = True 18 __unittest = True
16 19
17 20
18 DIFF_OMITTED = ('\nDiff is %s characters long. ' 21 DIFF_OMITTED = ('\nDiff is %s characters long. '
19 'Set self.maxDiff to None to see it.') 22 'Set self.maxDiff to None to see it.')
20 23
21 class SkipTest(Exception): 24 class SkipTest(Exception):
22 """ 25 """
23 Raise this exception in a test to skip it. 26 Raise this exception in a test to skip it.
24 27
25 Usually you can use TestResult.skip() or one of the skipping decorators 28 Usually you can use TestCase.skipTest() or one of the skipping decorators
26 instead of raising this directly. 29 instead of raising this directly.
27 """ 30 """
28 31
29 class _ExpectedFailure(Exception): 32 class _ShouldStop(Exception):
30 """ 33 """
31 Raise this when a test is expected to fail. 34 The test should stop.
32 35 """
33 This is an implementation detail.
34 """
35
36 def __init__(self, exc_info):
37 super(_ExpectedFailure, self).__init__()
38 self.exc_info = exc_info
39 36
40 class _UnexpectedSuccess(Exception): 37 class _UnexpectedSuccess(Exception):
41 """ 38 """
42 The test was supposed to fail, but it didn't! 39 The test was supposed to fail, but it didn't!
43 """ 40 """
44 41
45 42
46 class _Outcome(object): 43 class _Outcome(object):
47 def __init__(self): 44 def __init__(self, result=None):
45 self.expecting_failure = False
46 self.result = result
47 self.result_supports_subtests = hasattr(result, "addSubTest")
48 self.success = True 48 self.success = True
49 self.skipped = None 49 self.skipped = []
50 self.unexpectedSuccess = None
51 self.expectedFailure = None 50 self.expectedFailure = None
52 self.errors = [] 51 self.errors = []
53 self.failures = [] 52
53 @contextlib.contextmanager
54 def testPartExecutor(self, test_case, isTest=False):
55 old_success = self.success
56 self.success = True
57 try:
58 yield
59 except KeyboardInterrupt:
60 raise
61 except SkipTest as e:
62 self.success = False
63 self.skipped.append((test_case, str(e)))
64 except _ShouldStop:
65 pass
66 except:
67 exc_info = sys.exc_info()
68 if self.expecting_failure:
69 self.expectedFailure = exc_info
70 else:
71 self.success = False
72 self.errors.append((test_case, exc_info))
73 # explicitly break a reference cycle:
74 # exc_info -> frame -> exc_info
75 exc_info = None
76 else:
77 if self.result_supports_subtests and self.success:
78 self.errors.append((test_case, None))
79 finally:
80 self.success = self.success and old_success
54 81
55 82
56 def _id(obj): 83 def _id(obj):
57 return obj 84 return obj
58 85
59 def skip(reason): 86 def skip(reason):
60 """ 87 """
61 Unconditionally skip a test. 88 Unconditionally skip a test.
62 """ 89 """
63 def decorator(test_item): 90 def decorator(test_item):
(...skipping 17 matching lines...) Expand all
81 return _id 108 return _id
82 109
83 def skipUnless(condition, reason): 110 def skipUnless(condition, reason):
84 """ 111 """
85 Skip a test unless the condition is true. 112 Skip a test unless the condition is true.
86 """ 113 """
87 if not condition: 114 if not condition:
88 return skip(reason) 115 return skip(reason)
89 return _id 116 return _id
90 117
91 118 def expectedFailure(test_item):
92 def expectedFailure(func): 119 test_item.__unittest_expecting_failure__ = True
93 @functools.wraps(func) 120 return test_item
94 def wrapper(*args, **kwargs): 121
95 try: 122 def _is_subtype(expected, basetype):
96 func(*args, **kwargs) 123 if isinstance(expected, tuple):
97 except Exception: 124 return all(_is_subtype(e, basetype) for e in expected)
98 raise _ExpectedFailure(sys.exc_info()) 125 return isinstance(expected, type) and issubclass(expected, basetype)
99 raise _UnexpectedSuccess 126
100 return wrapper 127 class _BaseTestCaseContext:
101 128
102 def _ensure_is_exception_type(e): 129 def __init__(self, test_case):
103 if not isinstance(e, type) or not issubclass(e, BaseException):
104 raise TypeError('assertRaises arg 1 must be an exception type '
105 'or tuple of exception types')
106
107
108 class _AssertRaisesBaseContext(object):
109
110 def __init__(self, expected, test_case, callable_obj=None,
111 expected_regex=None):
112 self.expected = expected
113
114 if type(expected) is tuple:
115 for e in expected:
116 _ensure_is_exception_type(e)
117 else:
118 _ensure_is_exception_type(expected)
119
120 self.test_case = test_case 130 self.test_case = test_case
121 if callable_obj is not None:
122 try:
123 self.obj_name = callable_obj.__name__
124 except AttributeError:
125 self.obj_name = str(callable_obj)
126 else:
127 self.obj_name = None
128 if isinstance(expected_regex, (bytes, str)):
129 expected_regex = re.compile(expected_regex)
130 self.expected_regex = expected_regex
131 self.msg = None
132 131
133 def _raiseFailure(self, standardMsg): 132 def _raiseFailure(self, standardMsg):
134 msg = self.test_case._formatMessage(self.msg, standardMsg) 133 msg = self.test_case._formatMessage(self.msg, standardMsg)
135 raise self.test_case.failureException(msg) 134 raise self.test_case.failureException(msg)
136 135
137 def handle(self, name, callable_obj, args, kwargs): 136 class _AssertRaisesBaseContext(_BaseTestCaseContext):
138 """ 137
139 If callable_obj is None, assertRaises/Warns is being used as a 138 def __init__(self, expected, test_case, expected_regex=None):
139 _BaseTestCaseContext.__init__(self, test_case)
140 self.expected = expected
141 self.test_case = test_case
142 if expected_regex is not None:
143 expected_regex = re.compile(expected_regex)
144 self.expected_regex = expected_regex
145 self.obj_name = None
146 self.msg = None
147
148 def handle(self, name, args, kwargs):
149 """
150 If args is empty, assertRaises/Warns is being used as a
140 context manager, so check for a 'msg' kwarg and return self. 151 context manager, so check for a 'msg' kwarg and return self.
141 If callable_obj is not None, call it passing args and kwargs. 152 If args is not empty, call a callable passing positional and keyword
142 """ 153 arguments.
143 if callable_obj is None: 154 """
155 if not _is_subtype(self.expected, self._base_type):
Martin Panter 2015/05/19 12:37:58 Why is this check moved from __init__() to handle(
storchaka 2015/05/19 12:47:33 Only because the name parameter is passed to handl
Martin Panter 2015/05/19 13:27:57 Fair enough, that makes sense
156 raise TypeError('%s() arg 1 must be %s' %
157 (name, self._base_type_str))
158 if args and args[0] is None:
159 warnings.warn("callable is None",
160 DeprecationWarning, 3)
161 args = ()
162 if not args:
144 self.msg = kwargs.pop('msg', None) 163 self.msg = kwargs.pop('msg', None)
164 if kwargs:
165 warnings.warn('%r is an invalid keyword argument for '
166 'this function' % next(iter(kwargs)),
167 DeprecationWarning, 3)
145 return self 168 return self
169
170 callable_obj, *args = args
171 try:
172 self.obj_name = callable_obj.__name__
173 except AttributeError:
174 self.obj_name = str(callable_obj)
146 with self: 175 with self:
147 callable_obj(*args, **kwargs) 176 callable_obj(*args, **kwargs)
148 177
149 178
150
151 class _AssertRaisesContext(_AssertRaisesBaseContext): 179 class _AssertRaisesContext(_AssertRaisesBaseContext):
152 """A context manager used to implement TestCase.assertRaises* methods.""" 180 """A context manager used to implement TestCase.assertRaises* methods."""
181
182 _base_type = BaseException
183 _base_type_str = 'an exception type or tuple of exception types'
153 184
154 def __enter__(self): 185 def __enter__(self):
155 return self 186 return self
156 187
157 def __exit__(self, exc_type, exc_value, tb): 188 def __exit__(self, exc_type, exc_value, tb):
158 if exc_type is None: 189 if exc_type is None:
159 try: 190 try:
160 exc_name = self.expected.__name__ 191 exc_name = self.expected.__name__
161 except AttributeError: 192 except AttributeError:
162 exc_name = str(self.expected) 193 exc_name = str(self.expected)
163 if self.obj_name: 194 if self.obj_name:
164 self._raiseFailure("{} not raised by {}".format(exc_name, 195 self._raiseFailure("{} not raised by {}".format(exc_name,
165 self.obj_name)) 196 self.obj_name))
166 else: 197 else:
167 self._raiseFailure("{} not raised".format(exc_name)) 198 self._raiseFailure("{} not raised".format(exc_name))
199 else:
200 traceback.clear_frames(tb)
168 if not issubclass(exc_type, self.expected): 201 if not issubclass(exc_type, self.expected):
169 # let unexpected exceptions pass through 202 # let unexpected exceptions pass through
170 return False 203 return False
171 # store exception, without traceback, for later retrieval 204 # store exception, without traceback, for later retrieval
172 self.exception = exc_value.with_traceback(None) 205 self.exception = exc_value.with_traceback(None)
173 if self.expected_regex is None: 206 if self.expected_regex is None:
174 return True 207 return True
175 208
176 expected_regex = self.expected_regex 209 expected_regex = self.expected_regex
177 if not expected_regex.search(str(exc_value)): 210 if not expected_regex.search(str(exc_value)):
178 self._raiseFailure('"{}" does not match "{}"'.format( 211 self._raiseFailure('"{}" does not match "{}"'.format(
179 expected_regex.pattern, str(exc_value))) 212 expected_regex.pattern, str(exc_value)))
180 return True 213 return True
181 214
182 215
183 class _AssertWarnsContext(_AssertRaisesBaseContext): 216 class _AssertWarnsContext(_AssertRaisesBaseContext):
184 """A context manager used to implement TestCase.assertWarns* methods.""" 217 """A context manager used to implement TestCase.assertWarns* methods."""
218
219 _base_type = Warning
220 _base_type_str = 'a warning type or tuple of warning types'
185 221
186 def __enter__(self): 222 def __enter__(self):
187 # The __warningregistry__'s need to be in a pristine state for tests 223 # The __warningregistry__'s need to be in a pristine state for tests
188 # to work properly. 224 # to work properly.
189 for v in sys.modules.values(): 225 for v in sys.modules.values():
190 if getattr(v, '__warningregistry__', None): 226 if getattr(v, '__warningregistry__', None):
191 v.__warningregistry__ = {} 227 v.__warningregistry__ = {}
192 self.warnings_manager = warnings.catch_warnings(record=True) 228 self.warnings_manager = warnings.catch_warnings(record=True)
193 self.warnings = self.warnings_manager.__enter__() 229 self.warnings = self.warnings_manager.__enter__()
194 warnings.simplefilter("always", self.expected) 230 warnings.simplefilter("always", self.expected)
(...skipping 27 matching lines...) Expand all
222 if first_matching is not None: 258 if first_matching is not None:
223 self._raiseFailure('"{}" does not match "{}"'.format( 259 self._raiseFailure('"{}" does not match "{}"'.format(
224 self.expected_regex.pattern, str(first_matching))) 260 self.expected_regex.pattern, str(first_matching)))
225 if self.obj_name: 261 if self.obj_name:
226 self._raiseFailure("{} not triggered by {}".format(exc_name, 262 self._raiseFailure("{} not triggered by {}".format(exc_name,
227 self.obj_name)) 263 self.obj_name))
228 else: 264 else:
229 self._raiseFailure("{} not triggered".format(exc_name)) 265 self._raiseFailure("{} not triggered".format(exc_name))
230 266
231 267
268
269 _LoggingWatcher = collections.namedtuple("_LoggingWatcher",
270 ["records", "output"])
271
272
273 class _CapturingHandler(logging.Handler):
274 """
275 A logging handler capturing all (raw and formatted) logging output.
276 """
277
278 def __init__(self):
279 logging.Handler.__init__(self)
280 self.watcher = _LoggingWatcher([], [])
281
282 def flush(self):
283 pass
284
285 def emit(self, record):
286 self.watcher.records.append(record)
287 msg = self.format(record)
288 self.watcher.output.append(msg)
289
290
291
292 class _AssertLogsContext(_BaseTestCaseContext):
293 """A context manager used to implement TestCase.assertLogs()."""
294
295 LOGGING_FORMAT = "%(levelname)s:%(name)s:%(message)s"
296
297 def __init__(self, test_case, logger_name, level):
298 _BaseTestCaseContext.__init__(self, test_case)
299 self.logger_name = logger_name
300 if level:
301 self.level = logging._nameToLevel.get(level, level)
302 else:
303 self.level = logging.INFO
304 self.msg = None
305
306 def __enter__(self):
307 if isinstance(self.logger_name, logging.Logger):
308 logger = self.logger = self.logger_name
309 else:
310 logger = self.logger = logging.getLogger(self.logger_name)
311 formatter = logging.Formatter(self.LOGGING_FORMAT)
312 handler = _CapturingHandler()
313 handler.setFormatter(formatter)
314 self.watcher = handler.watcher
315 self.old_handlers = logger.handlers[:]
316 self.old_level = logger.level
317 self.old_propagate = logger.propagate
318 logger.handlers = [handler]
319 logger.setLevel(self.level)
320 logger.propagate = False
321 return handler.watcher
322
323 def __exit__(self, exc_type, exc_value, tb):
324 self.logger.handlers = self.old_handlers
325 self.logger.propagate = self.old_propagate
326 self.logger.setLevel(self.old_level)
327 if exc_type is not None:
328 # let unexpected exceptions pass through
329 return False
330 if len(self.watcher.records) == 0:
331 self._raiseFailure(
332 "no logs of level {} or higher triggered on {}"
333 .format(logging.getLevelName(self.level), self.logger.name))
334
335
232 class TestCase(object): 336 class TestCase(object):
233 """A class whose instances are single test cases. 337 """A class whose instances are single test cases.
234 338
235 By default, the test code itself should be placed in a method named 339 By default, the test code itself should be placed in a method named
236 'runTest'. 340 'runTest'.
237 341
238 If the fixture may be used for many test cases, create as 342 If the fixture may be used for many test cases, create as
239 many test methods as are needed. When instantiating such a TestCase 343 many test methods as are needed. When instantiating such a TestCase
240 subclass, specify in the constructor arguments the name of the test method 344 subclass, specify in the constructor arguments the name of the test method
241 that the instance is to execute. 345 that the instance is to execute.
242 346
243 Test authors should subclass TestCase for their own tests. Construction 347 Test authors should subclass TestCase for their own tests. Construction
244 and deconstruction of the test's environment ('fixture') can be 348 and deconstruction of the test's environment ('fixture') can be
245 implemented by overriding the 'setUp' and 'tearDown' methods respectively. 349 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
246 350
247 If it is necessary to override the __init__ method, the base class 351 If it is necessary to override the __init__ method, the base class
248 __init__ method must always be called. It is important that subclasses 352 __init__ method must always be called. It is important that subclasses
249 should not change the signature of their __init__ method, since instances 353 should not change the signature of their __init__ method, since instances
250 of the classes are instantiated automatically by parts of the framework 354 of the classes are instantiated automatically by parts of the framework
251 in order to be run. 355 in order to be run.
252 """ 356
253 357 When subclassing TestCase, you can set these attributes:
254 # This attribute determines which exception will be raised when 358 * failureException: determines which exception will be raised when
255 # the instance's assertion methods fail; test methods raising this 359 the instance's assertion methods fail; test methods raising this
256 # exception will be deemed to have 'failed' rather than 'errored' 360 exception will be deemed to have 'failed' rather than 'errored'.
361 * longMessage: determines whether long messages (including repr of
362 objects used in assert methods) will be printed on failure in *addition*
363 to any explicit message passed.
364 * maxDiff: sets the maximum length of a diff in failure messages
365 by assert methods using difflib. It is looked up as an instance
366 attribute so can be configured by individual tests if required.
367 """
257 368
258 failureException = AssertionError 369 failureException = AssertionError
259 370
260 # This attribute determines whether long messages (including repr of
261 # objects used in assert methods) will be printed on failure in *addition*
262 # to any explicit message passed.
263
264 longMessage = True 371 longMessage = True
265
266 # This attribute sets the maximum length of a diff in failure messages
267 # by assert methods using difflib. It is looked up as an instance attribute
268 # so can be configured by individual tests if required.
269 372
270 maxDiff = 80*8 373 maxDiff = 80*8
271 374
272 # If a string is longer than _diffThreshold, use normal comparison instead 375 # If a string is longer than _diffThreshold, use normal comparison instead
273 # of difflib. See #11763. 376 # of difflib. See #11763.
274 _diffThreshold = 2**16 377 _diffThreshold = 2**16
275 378
276 # Attribute used by TestSuite for classSetUp 379 # Attribute used by TestSuite for classSetUp
277 380
278 _classSetupFailed = False 381 _classSetupFailed = False
279 382
280 def __init__(self, methodName='runTest'): 383 def __init__(self, methodName='runTest'):
281 """Create an instance of the class that will use the named test 384 """Create an instance of the class that will use the named test
282 method when executed. Raises a ValueError if the instance does 385 method when executed. Raises a ValueError if the instance does
283 not have a method with the specified name. 386 not have a method with the specified name.
284 """ 387 """
285 self._testMethodName = methodName 388 self._testMethodName = methodName
286 self._outcomeForDoCleanups = None 389 self._outcome = None
287 self._testMethodDoc = 'No test' 390 self._testMethodDoc = 'No test'
288 try: 391 try:
289 testMethod = getattr(self, methodName) 392 testMethod = getattr(self, methodName)
290 except AttributeError: 393 except AttributeError:
291 if methodName != 'runTest': 394 if methodName != 'runTest':
292 # we allow instantiation with no explicit method name 395 # we allow instantiation with no explicit method name
293 # but not an *incorrect* or missing method name 396 # but not an *incorrect* or missing method name
294 raise ValueError("no such test method in %s: %s" % 397 raise ValueError("no such test method in %s: %s" %
295 (self.__class__, methodName)) 398 (self.__class__, methodName))
296 else: 399 else:
297 self._testMethodDoc = testMethod.__doc__ 400 self._testMethodDoc = testMethod.__doc__
298 self._cleanups = [] 401 self._cleanups = []
402 self._subtest = None
299 403
300 # Map types to custom assertEqual functions that will compare 404 # Map types to custom assertEqual functions that will compare
301 # instances of said type in more detail to generate a more useful 405 # instances of said type in more detail to generate a more useful
302 # error message. 406 # error message.
303 self._type_equality_funcs = {} 407 self._type_equality_funcs = {}
304 self.addTypeEqualityFunc(dict, 'assertDictEqual') 408 self.addTypeEqualityFunc(dict, 'assertDictEqual')
305 self.addTypeEqualityFunc(list, 'assertListEqual') 409 self.addTypeEqualityFunc(list, 'assertListEqual')
306 self.addTypeEqualityFunc(tuple, 'assertTupleEqual') 410 self.addTypeEqualityFunc(tuple, 'assertTupleEqual')
307 self.addTypeEqualityFunc(set, 'assertSetEqual') 411 self.addTypeEqualityFunc(set, 'assertSetEqual')
308 self.addTypeEqualityFunc(frozenset, 'assertSetEqual') 412 self.addTypeEqualityFunc(frozenset, 'assertSetEqual')
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 def __hash__(self): 480 def __hash__(self):
377 return hash((type(self), self._testMethodName)) 481 return hash((type(self), self._testMethodName))
378 482
379 def __str__(self): 483 def __str__(self):
380 return "%s (%s)" % (self._testMethodName, strclass(self.__class__)) 484 return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
381 485
382 def __repr__(self): 486 def __repr__(self):
383 return "<%s testMethod=%s>" % \ 487 return "<%s testMethod=%s>" % \
384 (strclass(self.__class__), self._testMethodName) 488 (strclass(self.__class__), self._testMethodName)
385 489
386 def _addSkip(self, result, reason): 490 def _addSkip(self, result, test_case, reason):
387 addSkip = getattr(result, 'addSkip', None) 491 addSkip = getattr(result, 'addSkip', None)
388 if addSkip is not None: 492 if addSkip is not None:
389 addSkip(self, reason) 493 addSkip(test_case, reason)
390 else: 494 else:
391 warnings.warn("TestResult has no addSkip method, skips not reported" , 495 warnings.warn("TestResult has no addSkip method, skips not reported" ,
392 RuntimeWarning, 2) 496 RuntimeWarning, 2)
497 result.addSuccess(test_case)
498
499 @contextlib.contextmanager
500 def subTest(self, msg=None, **params):
501 """Return a context manager that will return the enclosed block
502 of code in a subtest identified by the optional message and
503 keyword parameters. A failure in the subtest marks the test
504 case as failed but resumes execution at the end of the enclosed
505 block, allowing further test code to be executed.
506 """
507 if not self._outcome.result_supports_subtests:
508 yield
509 return
510 parent = self._subtest
511 if parent is None:
512 params_map = collections.ChainMap(params)
513 else:
514 params_map = parent.params.new_child(params)
515 self._subtest = _SubTest(self, msg, params_map)
516 try:
517 with self._outcome.testPartExecutor(self._subtest, isTest=True):
518 yield
519 if not self._outcome.success:
520 result = self._outcome.result
521 if result is not None and result.failfast:
522 raise _ShouldStop
523 elif self._outcome.expectedFailure:
524 # If the test is expecting a failure, we really want to
525 # stop now and register the expected failure.
526 raise _ShouldStop
527 finally:
528 self._subtest = parent
529
530 def _feedErrorsToResult(self, result, errors):
531 for test, exc_info in errors:
532 if isinstance(test, _SubTest):
533 result.addSubTest(test.test_case, test, exc_info)
534 elif exc_info is not None:
535 if issubclass(exc_info[0], self.failureException):
536 result.addFailure(test, exc_info)
537 else:
538 result.addError(test, exc_info)
539
540 def _addExpectedFailure(self, result, exc_info):
541 try:
542 addExpectedFailure = result.addExpectedFailure
543 except AttributeError:
544 warnings.warn("TestResult has no addExpectedFailure method, reportin g as passes",
545 RuntimeWarning)
393 result.addSuccess(self) 546 result.addSuccess(self)
394 547 else:
395 def _executeTestPart(self, function, outcome, isTest=False): 548 addExpectedFailure(self, exc_info)
549
550 def _addUnexpectedSuccess(self, result):
396 try: 551 try:
397 function() 552 addUnexpectedSuccess = result.addUnexpectedSuccess
398 except KeyboardInterrupt: 553 except AttributeError:
399 raise 554 warnings.warn("TestResult has no addUnexpectedSuccess method, report ing as failure",
400 except SkipTest as e: 555 RuntimeWarning)
401 outcome.success = False 556 # We need to pass an actual exception and traceback to addFailure,
402 outcome.skipped = str(e) 557 # otherwise the legacy result can choke.
403 except _UnexpectedSuccess: 558 try:
404 exc_info = sys.exc_info() 559 raise _UnexpectedSuccess from None
405 outcome.success = False 560 except _UnexpectedSuccess:
406 if isTest: 561 result.addFailure(self, sys.exc_info())
407 outcome.unexpectedSuccess = exc_info 562 else:
408 else: 563 addUnexpectedSuccess(self)
409 outcome.errors.append(exc_info)
410 except _ExpectedFailure:
411 outcome.success = False
412 exc_info = sys.exc_info()
413 if isTest:
414 outcome.expectedFailure = exc_info
415 else:
416 outcome.errors.append(exc_info)
417 except self.failureException:
418 outcome.success = False
419 outcome.failures.append(sys.exc_info())
420 exc_info = sys.exc_info()
421 except:
422 outcome.success = False
423 outcome.errors.append(sys.exc_info())
424 564
425 def run(self, result=None): 565 def run(self, result=None):
426 orig_result = result 566 orig_result = result
427 if result is None: 567 if result is None:
428 result = self.defaultTestResult() 568 result = self.defaultTestResult()
429 startTestRun = getattr(result, 'startTestRun', None) 569 startTestRun = getattr(result, 'startTestRun', None)
430 if startTestRun is not None: 570 if startTestRun is not None:
431 startTestRun() 571 startTestRun()
432 572
433 result.startTest(self) 573 result.startTest(self)
434 574
435 testMethod = getattr(self, self._testMethodName) 575 testMethod = getattr(self, self._testMethodName)
436 if (getattr(self.__class__, "__unittest_skip__", False) or 576 if (getattr(self.__class__, "__unittest_skip__", False) or
437 getattr(testMethod, "__unittest_skip__", False)): 577 getattr(testMethod, "__unittest_skip__", False)):
438 # If the class or method was skipped. 578 # If the class or method was skipped.
439 try: 579 try:
440 skip_why = (getattr(self.__class__, '__unittest_skip_why__', '') 580 skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
441 or getattr(testMethod, '__unittest_skip_why__', '')) 581 or getattr(testMethod, '__unittest_skip_why__', ''))
442 self._addSkip(result, skip_why) 582 self._addSkip(result, self, skip_why)
443 finally: 583 finally:
444 result.stopTest(self) 584 result.stopTest(self)
445 return 585 return
586 expecting_failure = getattr(testMethod,
587 "__unittest_expecting_failure__", False)
588 outcome = _Outcome(result)
446 try: 589 try:
447 outcome = _Outcome() 590 self._outcome = outcome
448 self._outcomeForDoCleanups = outcome 591
449 592 with outcome.testPartExecutor(self):
450 self._executeTestPart(self.setUp, outcome) 593 self.setUp()
451 if outcome.success: 594 if outcome.success:
452 self._executeTestPart(testMethod, outcome, isTest=True) 595 outcome.expecting_failure = expecting_failure
453 self._executeTestPart(self.tearDown, outcome) 596 with outcome.testPartExecutor(self, isTest=True):
597 testMethod()
598 outcome.expecting_failure = False
599 with outcome.testPartExecutor(self):
600 self.tearDown()
454 601
455 self.doCleanups() 602 self.doCleanups()
603 for test, reason in outcome.skipped:
604 self._addSkip(result, test, reason)
605 self._feedErrorsToResult(result, outcome.errors)
456 if outcome.success: 606 if outcome.success:
457 result.addSuccess(self) 607 if expecting_failure:
458 else: 608 if outcome.expectedFailure:
459 if outcome.skipped is not None: 609 self._addExpectedFailure(result, outcome.expectedFailure )
460 self._addSkip(result, outcome.skipped)
461 for exc_info in outcome.errors:
462 result.addError(self, exc_info)
463 for exc_info in outcome.failures:
464 result.addFailure(self, exc_info)
465 if outcome.unexpectedSuccess is not None:
466 addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess ', None)
467 if addUnexpectedSuccess is not None:
468 addUnexpectedSuccess(self)
469 else: 610 else:
470 warnings.warn("TestResult has no addUnexpectedSuccess me thod, reporting as failures", 611 self._addUnexpectedSuccess(result)
471 RuntimeWarning) 612 else:
472 result.addFailure(self, outcome.unexpectedSuccess) 613 result.addSuccess(self)
473
474 if outcome.expectedFailure is not None:
475 addExpectedFailure = getattr(result, 'addExpectedFailure', N one)
476 if addExpectedFailure is not None:
477 addExpectedFailure(self, outcome.expectedFailure)
478 else:
479 warnings.warn("TestResult has no addExpectedFailure meth od, reporting as passes",
480 RuntimeWarning)
481 result.addSuccess(self)
482 return result 614 return result
483 finally: 615 finally:
484 result.stopTest(self) 616 result.stopTest(self)
485 if orig_result is None: 617 if orig_result is None:
486 stopTestRun = getattr(result, 'stopTestRun', None) 618 stopTestRun = getattr(result, 'stopTestRun', None)
487 if stopTestRun is not None: 619 if stopTestRun is not None:
488 stopTestRun() 620 stopTestRun()
489 621
622 # explicitly break reference cycles:
623 # outcome.errors -> frame -> outcome -> outcome.errors
624 # outcome.expectedFailure -> frame -> outcome -> outcome.expectedFai lure
625 outcome.errors.clear()
626 outcome.expectedFailure = None
627
628 # clear the outcome, no more needed
629 self._outcome = None
630
490 def doCleanups(self): 631 def doCleanups(self):
491 """Execute all cleanup functions. Normally called for you after 632 """Execute all cleanup functions. Normally called for you after
492 tearDown.""" 633 tearDown."""
493 outcome = self._outcomeForDoCleanups or _Outcome() 634 outcome = self._outcome or _Outcome()
494 while self._cleanups: 635 while self._cleanups:
495 function, args, kwargs = self._cleanups.pop() 636 function, args, kwargs = self._cleanups.pop()
496 part = lambda: function(*args, **kwargs) 637 with outcome.testPartExecutor(self):
497 self._executeTestPart(part, outcome) 638 function(*args, **kwargs)
498 639
499 # return this for backwards compatibility 640 # return this for backwards compatibility
500 # even though we no longer us it internally 641 # even though we no longer us it internally
501 return outcome.success 642 return outcome.success
502 643
503 def __call__(self, *args, **kwds): 644 def __call__(self, *args, **kwds):
504 return self.run(*args, **kwds) 645 return self.run(*args, **kwds)
505 646
506 def debug(self): 647 def debug(self):
507 """Run the test without collecting errors in a TestResult""" 648 """Run the test without collecting errors in a TestResult"""
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 return msg or standardMsg 687 return msg or standardMsg
547 if msg is None: 688 if msg is None:
548 return standardMsg 689 return standardMsg
549 try: 690 try:
550 # don't switch to '{}' formatting in Python 2.X 691 # don't switch to '{}' formatting in Python 2.X
551 # it changes the way unicode input is handled 692 # it changes the way unicode input is handled
552 return '%s : %s' % (standardMsg, msg) 693 return '%s : %s' % (standardMsg, msg)
553 except UnicodeDecodeError: 694 except UnicodeDecodeError:
554 return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg)) 695 return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
555 696
556 def assertRaises(self, excClass, callableObj=None, *args, **kwargs): 697 def assertRaises(self, expected_exception, *args, **kwargs):
557 """Fail unless an exception of class excClass is thrown 698 """Fail unless an exception of class expected_exception is raised
558 by callableObj when invoked with arguments args and keyword 699 by the callable when invoked with specified positional and
559 arguments kwargs. If a different type of exception is 700 keyword arguments. If a different type of exception is
560 thrown, it will not be caught, and the test case will be 701 raised, it will not be caught, and the test case will be
561 deemed to have suffered an error, exactly as for an 702 deemed to have suffered an error, exactly as for an
562 unexpected exception. 703 unexpected exception.
563 704
564 If called with callableObj omitted or None, will return a 705 If called with the callable and arguments omitted, will return a
565 context object used like this:: 706 context object used like this::
566 707
567 with self.assertRaises(SomeException): 708 with self.assertRaises(SomeException):
568 do_something() 709 do_something()
569 710
570 An optional keyword argument 'msg' can be provided when assertRaises 711 An optional keyword argument 'msg' can be provided when assertRaises
571 is used as a context object. 712 is used as a context object.
572 713
573 The context manager keeps a reference to the exception as 714 The context manager keeps a reference to the exception as
574 the 'exception' attribute. This allows you to inspect the 715 the 'exception' attribute. This allows you to inspect the
575 exception after the assertion:: 716 exception after the assertion::
576 717
577 with self.assertRaises(SomeException) as cm: 718 with self.assertRaises(SomeException) as cm:
578 do_something() 719 do_something()
579 the_exception = cm.exception 720 the_exception = cm.exception
580 self.assertEqual(the_exception.error_code, 3) 721 self.assertEqual(the_exception.error_code, 3)
581 """ 722 """
582 context = _AssertRaisesContext(excClass, self, callableObj) 723 context = _AssertRaisesContext(expected_exception, self)
583 return context.handle('assertRaises', callableObj, args, kwargs) 724 return context.handle('assertRaises', args, kwargs)
584 725
585 def assertWarns(self, expected_warning, callable_obj=None, *args, **kwargs): 726 def assertWarns(self, expected_warning, *args, **kwargs):
586 """Fail unless a warning of class warnClass is triggered 727 """Fail unless a warning of class warnClass is triggered
587 by callable_obj when invoked with arguments args and keyword 728 by the callable when invoked with specified positional and
588 arguments kwargs. If a different type of warning is 729 keyword arguments. If a different type of warning is
589 triggered, it will not be handled: depending on the other 730 triggered, it will not be handled: depending on the other
590 warning filtering rules in effect, it might be silenced, printed 731 warning filtering rules in effect, it might be silenced, printed
591 out, or raised as an exception. 732 out, or raised as an exception.
592 733
593 If called with callable_obj omitted or None, will return a 734 If called with the callable and arguments omitted, will return a
594 context object used like this:: 735 context object used like this::
595 736
596 with self.assertWarns(SomeWarning): 737 with self.assertWarns(SomeWarning):
597 do_something() 738 do_something()
598 739
599 An optional keyword argument 'msg' can be provided when assertWarns 740 An optional keyword argument 'msg' can be provided when assertWarns
600 is used as a context object. 741 is used as a context object.
601 742
602 The context manager keeps a reference to the first matching 743 The context manager keeps a reference to the first matching
603 warning as the 'warning' attribute; similarly, the 'filename' 744 warning as the 'warning' attribute; similarly, the 'filename'
604 and 'lineno' attributes give you information about the line 745 and 'lineno' attributes give you information about the line
605 of Python code from which the warning was triggered. 746 of Python code from which the warning was triggered.
606 This allows you to inspect the warning after the assertion:: 747 This allows you to inspect the warning after the assertion::
607 748
608 with self.assertWarns(SomeWarning) as cm: 749 with self.assertWarns(SomeWarning) as cm:
609 do_something() 750 do_something()
610 the_warning = cm.warning 751 the_warning = cm.warning
611 self.assertEqual(the_warning.some_attribute, 147) 752 self.assertEqual(the_warning.some_attribute, 147)
612 """ 753 """
613 context = _AssertWarnsContext(expected_warning, self, callable_obj) 754 context = _AssertWarnsContext(expected_warning, self)
614 return context.handle('assertWarns', callable_obj, args, kwargs) 755 return context.handle('assertWarns', args, kwargs)
756
757 def assertLogs(self, logger=None, level=None):
758 """Fail unless a log message of level *level* or higher is emitted
759 on *logger_name* or its children. If omitted, *level* defaults to
760 INFO and *logger* defaults to the root logger.
761
762 This method must be used as a context manager, and will yield
763 a recording object with two attributes: `output` and `records`.
764 At the end of the context manager, the `output` attribute will
765 be a list of the matching formatted log messages and the
766 `records` attribute will be a list of the corresponding LogRecord
767 objects.
768
769 Example::
770
771 with self.assertLogs('foo', level='INFO') as cm:
772 logging.getLogger('foo').info('first message')
773 logging.getLogger('foo.bar').error('second message')
774 self.assertEqual(cm.output, ['INFO:foo:first message',
775 'ERROR:foo.bar:second message'])
776 """
777 return _AssertLogsContext(self, logger, level)
615 778
616 def _getAssertEqualityFunc(self, first, second): 779 def _getAssertEqualityFunc(self, first, second):
617 """Get a detailed comparison function for the types of the two args. 780 """Get a detailed comparison function for the types of the two args.
618 781
619 Returns: A callable accepting (first, second, msg=None) that will 782 Returns: A callable accepting (first, second, msg=None) that will
620 raise a failure exception if first != second with a useful human 783 raise a failure exception if first != second with a useful human
621 readable error message for those types. 784 readable error message for those types.
622 """ 785 """
623 # 786 #
624 # NOTE(gregory.p.smith): I considered isinstance(first, type(second)) 787 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
(...skipping 10 matching lines...) Expand all
635 if asserter is not None: 798 if asserter is not None:
636 if isinstance(asserter, str): 799 if isinstance(asserter, str):
637 asserter = getattr(self, asserter) 800 asserter = getattr(self, asserter)
638 return asserter 801 return asserter
639 802
640 return self._baseAssertEqual 803 return self._baseAssertEqual
641 804
642 def _baseAssertEqual(self, first, second, msg=None): 805 def _baseAssertEqual(self, first, second, msg=None):
643 """The default assertEqual implementation, not type specific.""" 806 """The default assertEqual implementation, not type specific."""
644 if not first == second: 807 if not first == second:
645 standardMsg = '%s != %s' % (safe_repr(first), safe_repr(second)) 808 standardMsg = '%s != %s' % _common_shorten_repr(first, second)
646 msg = self._formatMessage(msg, standardMsg) 809 msg = self._formatMessage(msg, standardMsg)
647 raise self.failureException(msg) 810 raise self.failureException(msg)
648 811
649 def assertEqual(self, first, second, msg=None): 812 def assertEqual(self, first, second, msg=None):
650 """Fail if the two objects are unequal as determined by the '==' 813 """Fail if the two objects are unequal as determined by the '=='
651 operator. 814 operator.
652 """ 815 """
653 assertion_func = self._getAssertEqualityFunc(first, second) 816 assertion_func = self._getAssertEqualityFunc(first, second)
654 assertion_func(first, second, msg=msg) 817 assertion_func(first, second, msg=msg)
655 818
656 def assertNotEqual(self, first, second, msg=None): 819 def assertNotEqual(self, first, second, msg=None):
657 """Fail if the two objects are equal as determined by the '==' 820 """Fail if the two objects are equal as determined by the '!='
658 operator. 821 operator.
659 """ 822 """
660 if not first != second: 823 if not first != second:
661 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first), 824 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
662 safe_repr(second))) 825 safe_repr(second)))
663 raise self.failureException(msg) 826 raise self.failureException(msg)
664 827
665 def assertAlmostEqual(self, first, second, places=None, msg=None, 828 def assertAlmostEqual(self, first, second, places=None, msg=None,
666 delta=None): 829 delta=None):
667 """Fail if the two objects are unequal as determined by their 830 """Fail if the two objects are unequal as determined by their
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 which can be indexed, has a length, and has an equality operator. 904 which can be indexed, has a length, and has an equality operator.
742 905
743 Args: 906 Args:
744 seq1: The first sequence to compare. 907 seq1: The first sequence to compare.
745 seq2: The second sequence to compare. 908 seq2: The second sequence to compare.
746 seq_type: The expected datatype of the sequences, or None if no 909 seq_type: The expected datatype of the sequences, or None if no
747 datatype should be enforced. 910 datatype should be enforced.
748 msg: Optional message to use on failure instead of a list of 911 msg: Optional message to use on failure instead of a list of
749 differences. 912 differences.
750 """ 913 """
751 if seq_type != None: 914 if seq_type is not None:
752 seq_type_name = seq_type.__name__ 915 seq_type_name = seq_type.__name__
753 if not isinstance(seq1, seq_type): 916 if not isinstance(seq1, seq_type):
754 raise self.failureException('First sequence is not a %s: %s' 917 raise self.failureException('First sequence is not a %s: %s'
755 % (seq_type_name, safe_repr(seq1))) 918 % (seq_type_name, safe_repr(seq1)))
756 if not isinstance(seq2, seq_type): 919 if not isinstance(seq2, seq_type):
757 raise self.failureException('Second sequence is not a %s: %s' 920 raise self.failureException('Second sequence is not a %s: %s'
758 % (seq_type_name, safe_repr(seq2))) 921 % (seq_type_name, safe_repr(seq2)))
759 else: 922 else:
760 seq_type_name = "sequence" 923 seq_type_name = "sequence"
761 924
762 differing = None 925 differing = None
763 try: 926 try:
764 len1 = len(seq1) 927 len1 = len(seq1)
765 except (TypeError, NotImplementedError): 928 except (TypeError, NotImplementedError):
766 differing = 'First %s has no length. Non-sequence?' % ( 929 differing = 'First %s has no length. Non-sequence?' % (
767 seq_type_name) 930 seq_type_name)
768 931
769 if differing is None: 932 if differing is None:
770 try: 933 try:
771 len2 = len(seq2) 934 len2 = len(seq2)
772 except (TypeError, NotImplementedError): 935 except (TypeError, NotImplementedError):
773 differing = 'Second %s has no length. Non-sequence?' % ( 936 differing = 'Second %s has no length. Non-sequence?' % (
774 seq_type_name) 937 seq_type_name)
775 938
776 if differing is None: 939 if differing is None:
777 if seq1 == seq2: 940 if seq1 == seq2:
778 return 941 return
779 942
780 seq1_repr = safe_repr(seq1) 943 differing = '%ss differ: %s != %s\n' % (
781 seq2_repr = safe_repr(seq2) 944 (seq_type_name.capitalize(),) +
782 if len(seq1_repr) > 30: 945 _common_shorten_repr(seq1, seq2))
783 seq1_repr = seq1_repr[:30] + '...'
784 if len(seq2_repr) > 30:
785 seq2_repr = seq2_repr[:30] + '...'
786 elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
787 differing = '%ss differ: %s != %s\n' % elements
788 946
789 for i in range(min(len1, len2)): 947 for i in range(min(len1, len2)):
790 try: 948 try:
791 item1 = seq1[i] 949 item1 = seq1[i]
792 except (TypeError, IndexError, NotImplementedError): 950 except (TypeError, IndexError, NotImplementedError):
793 differing += ('\nUnable to index element %d of first %s\n' % 951 differing += ('\nUnable to index element %d of first %s\n' %
794 (i, seq_type_name)) 952 (i, seq_type_name))
795 break 953 break
796 954
797 try: 955 try:
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 """Just like self.assertTrue(a is not b), but with a nicer default messa ge.""" 1093 """Just like self.assertTrue(a is not b), but with a nicer default messa ge."""
936 if expr1 is expr2: 1094 if expr1 is expr2:
937 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),) 1095 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
938 self.fail(self._formatMessage(msg, standardMsg)) 1096 self.fail(self._formatMessage(msg, standardMsg))
939 1097
940 def assertDictEqual(self, d1, d2, msg=None): 1098 def assertDictEqual(self, d1, d2, msg=None):
941 self.assertIsInstance(d1, dict, 'First argument is not a dictionary') 1099 self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
942 self.assertIsInstance(d2, dict, 'Second argument is not a dictionary') 1100 self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')
943 1101
944 if d1 != d2: 1102 if d1 != d2:
945 standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True) ) 1103 standardMsg = '%s != %s' % _common_shorten_repr(d1, d2)
946 diff = ('\n' + '\n'.join(difflib.ndiff( 1104 diff = ('\n' + '\n'.join(difflib.ndiff(
947 pprint.pformat(d1).splitlines(), 1105 pprint.pformat(d1).splitlines(),
948 pprint.pformat(d2).splitlines()))) 1106 pprint.pformat(d2).splitlines())))
949 standardMsg = self._truncateMessage(standardMsg, diff) 1107 standardMsg = self._truncateMessage(standardMsg, diff)
950 self.fail(self._formatMessage(msg, standardMsg)) 1108 self.fail(self._formatMessage(msg, standardMsg))
951 1109
952 def assertDictContainsSubset(self, subset, dictionary, msg=None): 1110 def assertDictContainsSubset(self, subset, dictionary, msg=None):
953 """Checks whether dictionary is a superset of subset.""" 1111 """Checks whether dictionary is a superset of subset."""
954 warnings.warn('assertDictContainsSubset is deprecated', 1112 warnings.warn('assertDictContainsSubset is deprecated',
955 DeprecationWarning) 1113 DeprecationWarning)
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 if first != second: 1177 if first != second:
1020 # don't use difflib if the strings are too long 1178 # don't use difflib if the strings are too long
1021 if (len(first) > self._diffThreshold or 1179 if (len(first) > self._diffThreshold or
1022 len(second) > self._diffThreshold): 1180 len(second) > self._diffThreshold):
1023 self._baseAssertEqual(first, second, msg) 1181 self._baseAssertEqual(first, second, msg)
1024 firstlines = first.splitlines(keepends=True) 1182 firstlines = first.splitlines(keepends=True)
1025 secondlines = second.splitlines(keepends=True) 1183 secondlines = second.splitlines(keepends=True)
1026 if len(firstlines) == 1 and first.strip('\r\n') == first: 1184 if len(firstlines) == 1 and first.strip('\r\n') == first:
1027 firstlines = [first + '\n'] 1185 firstlines = [first + '\n']
1028 secondlines = [second + '\n'] 1186 secondlines = [second + '\n']
1029 standardMsg = '%s != %s' % (safe_repr(first, True), 1187 standardMsg = '%s != %s' % _common_shorten_repr(first, second)
1030 safe_repr(second, True))
1031 diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines)) 1188 diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines))
1032 standardMsg = self._truncateMessage(standardMsg, diff) 1189 standardMsg = self._truncateMessage(standardMsg, diff)
1033 self.fail(self._formatMessage(msg, standardMsg)) 1190 self.fail(self._formatMessage(msg, standardMsg))
1034 1191
1035 def assertLess(self, a, b, msg=None): 1192 def assertLess(self, a, b, msg=None):
1036 """Just like self.assertTrue(a < b), but with a nicer default message."" " 1193 """Just like self.assertTrue(a < b), but with a nicer default message."" "
1037 if not a < b: 1194 if not a < b:
1038 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b)) 1195 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
1039 self.fail(self._formatMessage(msg, standardMsg)) 1196 self.fail(self._formatMessage(msg, standardMsg))
1040 1197
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls) 1232 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
1076 self.fail(self._formatMessage(msg, standardMsg)) 1233 self.fail(self._formatMessage(msg, standardMsg))
1077 1234
1078 def assertNotIsInstance(self, obj, cls, msg=None): 1235 def assertNotIsInstance(self, obj, cls, msg=None):
1079 """Included for symmetry with assertIsInstance.""" 1236 """Included for symmetry with assertIsInstance."""
1080 if isinstance(obj, cls): 1237 if isinstance(obj, cls):
1081 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls) 1238 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
1082 self.fail(self._formatMessage(msg, standardMsg)) 1239 self.fail(self._formatMessage(msg, standardMsg))
1083 1240
1084 def assertRaisesRegex(self, expected_exception, expected_regex, 1241 def assertRaisesRegex(self, expected_exception, expected_regex,
1085 callable_obj=None, *args, **kwargs): 1242 *args, **kwargs):
1086 """Asserts that the message in a raised exception matches a regex. 1243 """Asserts that the message in a raised exception matches a regex.
1087 1244
1088 Args: 1245 Args:
1089 expected_exception: Exception class expected to be raised. 1246 expected_exception: Exception class expected to be raised.
1090 expected_regex: Regex (re pattern object or string) expected 1247 expected_regex: Regex (re pattern object or string) expected
1091 to be found in error message. 1248 to be found in error message.
1092 callable_obj: Function to be called. 1249 args: Function to be called and extra positional args.
1250 kwargs: Extra kwargs.
1093 msg: Optional message used in case of failure. Can only be used 1251 msg: Optional message used in case of failure. Can only be used
1094 when assertRaisesRegex is used as a context manager. 1252 when assertRaisesRegex is used as a context manager.
1095 args: Extra args. 1253 """
1096 kwargs: Extra kwargs. 1254 context = _AssertRaisesContext(expected_exception, self, expected_regex)
1097 """ 1255 return context.handle('assertRaisesRegex', args, kwargs)
1098 context = _AssertRaisesContext(expected_exception, self, callable_obj,
1099 expected_regex)
1100
1101 return context.handle('assertRaisesRegex', callable_obj, args, kwargs)
1102 1256
1103 def assertWarnsRegex(self, expected_warning, expected_regex, 1257 def assertWarnsRegex(self, expected_warning, expected_regex,
1104 callable_obj=None, *args, **kwargs): 1258 *args, **kwargs):
1105 """Asserts that the message in a triggered warning matches a regexp. 1259 """Asserts that the message in a triggered warning matches a regexp.
1106 Basic functioning is similar to assertWarns() with the addition 1260 Basic functioning is similar to assertWarns() with the addition
1107 that only warnings whose messages also match the regular expression 1261 that only warnings whose messages also match the regular expression
1108 are considered successful matches. 1262 are considered successful matches.
1109 1263
1110 Args: 1264 Args:
1111 expected_warning: Warning class expected to be triggered. 1265 expected_warning: Warning class expected to be triggered.
1112 expected_regex: Regex (re pattern object or string) expected 1266 expected_regex: Regex (re pattern object or string) expected
1113 to be found in error message. 1267 to be found in error message.
1114 callable_obj: Function to be called. 1268 args: Function to be called and extra positional args.
1269 kwargs: Extra kwargs.
1115 msg: Optional message used in case of failure. Can only be used 1270 msg: Optional message used in case of failure. Can only be used
1116 when assertWarnsRegex is used as a context manager. 1271 when assertWarnsRegex is used as a context manager.
1117 args: Extra args. 1272 """
1118 kwargs: Extra kwargs. 1273 context = _AssertWarnsContext(expected_warning, self, expected_regex)
1119 """ 1274 return context.handle('assertWarnsRegex', args, kwargs)
1120 context = _AssertWarnsContext(expected_warning, self, callable_obj,
1121 expected_regex)
1122 return context.handle('assertWarnsRegex', callable_obj, args, kwargs)
1123 1275
1124 def assertRegex(self, text, expected_regex, msg=None): 1276 def assertRegex(self, text, expected_regex, msg=None):
1125 """Fail the test unless the text matches the regular expression.""" 1277 """Fail the test unless the text matches the regular expression."""
1126 if isinstance(expected_regex, (str, bytes)): 1278 if isinstance(expected_regex, (str, bytes)):
1127 assert expected_regex, "expected_regex must not be empty." 1279 assert expected_regex, "expected_regex must not be empty."
1128 expected_regex = re.compile(expected_regex) 1280 expected_regex = re.compile(expected_regex)
1129 if not expected_regex.search(text): 1281 if not expected_regex.search(text):
1130 msg = msg or "Regex didn't match" 1282 msg = msg or "Regex didn't match"
1131 msg = '%s: %r not found in %r' % (msg, expected_regex.pattern, text) 1283 msg = '%s: %r not found in %r' % (msg, expected_regex.pattern, text)
1132 raise self.failureException(msg) 1284 raise self.failureException(msg)
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1198 1350
1199 def __eq__(self, other): 1351 def __eq__(self, other):
1200 if not isinstance(other, self.__class__): 1352 if not isinstance(other, self.__class__):
1201 return NotImplemented 1353 return NotImplemented
1202 1354
1203 return self._setUpFunc == other._setUpFunc and \ 1355 return self._setUpFunc == other._setUpFunc and \
1204 self._tearDownFunc == other._tearDownFunc and \ 1356 self._tearDownFunc == other._tearDownFunc and \
1205 self._testFunc == other._testFunc and \ 1357 self._testFunc == other._testFunc and \
1206 self._description == other._description 1358 self._description == other._description
1207 1359
1208 def __ne__(self, other):
1209 return not self == other
1210
1211 def __hash__(self): 1360 def __hash__(self):
1212 return hash((type(self), self._setUpFunc, self._tearDownFunc, 1361 return hash((type(self), self._setUpFunc, self._tearDownFunc,
1213 self._testFunc, self._description)) 1362 self._testFunc, self._description))
1214 1363
1215 def __str__(self): 1364 def __str__(self):
1216 return "%s (%s)" % (strclass(self.__class__), 1365 return "%s (%s)" % (strclass(self.__class__),
1217 self._testFunc.__name__) 1366 self._testFunc.__name__)
1218 1367
1219 def __repr__(self): 1368 def __repr__(self):
1220 return "<%s tec=%s>" % (strclass(self.__class__), 1369 return "<%s tec=%s>" % (strclass(self.__class__),
1221 self._testFunc) 1370 self._testFunc)
1222 1371
1223 def shortDescription(self): 1372 def shortDescription(self):
1224 if self._description is not None: 1373 if self._description is not None:
1225 return self._description 1374 return self._description
1226 doc = self._testFunc.__doc__ 1375 doc = self._testFunc.__doc__
1227 return doc and doc.split("\n")[0].strip() or None 1376 return doc and doc.split("\n")[0].strip() or None
1377
1378
1379 class _SubTest(TestCase):
1380
1381 def __init__(self, test_case, message, params):
1382 super().__init__()
1383 self._message = message
1384 self.test_case = test_case
1385 self.params = params
1386 self.failureException = test_case.failureException
1387
1388 def runTest(self):
1389 raise NotImplementedError("subtests cannot be run directly")
1390
1391 def _subDescription(self):
1392 parts = []
1393 if self._message:
1394 parts.append("[{}]".format(self._message))
1395 if self.params:
1396 params_desc = ', '.join(
1397 "{}={!r}".format(k, v)
1398 for (k, v) in sorted(self.params.items()))
1399 parts.append("({})".format(params_desc))
1400 return " ".join(parts) or '(<subtest>)'
1401
1402 def id(self):
1403 return "{} {}".format(self.test_case.id(), self._subDescription())
1404
1405 def shortDescription(self):
1406 """Returns a one-line description of the subtest, or None if no
1407 description has been provided.
1408 """
1409 return self.test_case.shortDescription()
1410
1411 def __str__(self):
1412 return "{} {}".format(self.test_case, self._subDescription())
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+