blob: 7701ad3adcc22612f0c74e86b5550d83f584262f [file] [log] [blame]
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001"""Test case implementation"""
2
3import sys
4import functools
5import difflib
Antoine Pitrou0715b9f2013-09-14 19:45:47 +02006import logging
Benjamin Petersonbed7d042009-07-19 21:01:52 +00007import pprint
8import re
9import warnings
Raymond Hettinger6e165b32010-11-27 09:31:37 +000010import collections
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010011import contextlib
Antoine Pitrou96810222014-04-29 01:23:50 +020012import traceback
Benjamin Petersonbed7d042009-07-19 21:01:52 +000013
Benjamin Peterson847a4112010-03-14 15:04:17 +000014from . import result
Florent Xiclunac53ae582011-11-04 08:25:54 +010015from .util import (strclass, safe_repr, _count_diff_all_purpose,
Serhiy Storchaka77622f52013-09-23 23:07:00 +030016 _count_diff_hashable, _common_shorten_repr)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000017
Benjamin Petersondccc1fc2010-03-22 00:15:53 +000018__unittest = True
Benjamin Petersonbed7d042009-07-19 21:01:52 +000019
Michael Foord9dad32e2010-06-05 13:49:56 +000020
21DIFF_OMITTED = ('\nDiff is %s characters long. '
22 'Set self.maxDiff to None to see it.')
23
Benjamin Petersonbed7d042009-07-19 21:01:52 +000024class SkipTest(Exception):
25 """
26 Raise this exception in a test to skip it.
27
Ezio Melotti265281a2013-03-27 20:11:55 +020028 Usually you can use TestCase.skipTest() or one of the skipping decorators
Benjamin Petersonbed7d042009-07-19 21:01:52 +000029 instead of raising this directly.
30 """
Benjamin Petersonbed7d042009-07-19 21:01:52 +000031
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010032class _ShouldStop(Exception):
Benjamin Petersonbed7d042009-07-19 21:01:52 +000033 """
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010034 The test should stop.
Benjamin Petersonbed7d042009-07-19 21:01:52 +000035 """
36
Benjamin Petersonbed7d042009-07-19 21:01:52 +000037class _UnexpectedSuccess(Exception):
38 """
39 The test was supposed to fail, but it didn't!
40 """
Michael Foordb3468f72010-12-19 03:19:47 +000041
42
43class _Outcome(object):
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010044 def __init__(self, result=None):
45 self.expecting_failure = False
46 self.result = result
47 self.result_supports_subtests = hasattr(result, "addSubTest")
Michael Foordb3468f72010-12-19 03:19:47 +000048 self.success = True
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010049 self.skipped = []
Michael Foordb3468f72010-12-19 03:19:47 +000050 self.expectedFailure = None
51 self.errors = []
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010052
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))
Victor Stinner031bd532013-12-09 01:52:50 +010073 # explicitly break a reference cycle:
74 # exc_info -> frame -> exc_info
75 exc_info = None
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010076 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
Michael Foordb3468f72010-12-19 03:19:47 +000081
Benjamin Petersonbed7d042009-07-19 21:01:52 +000082
83def _id(obj):
84 return obj
85
86def skip(reason):
87 """
88 Unconditionally skip a test.
89 """
90 def decorator(test_item):
Antoine Pitroub05ac862012-04-25 14:56:46 +020091 if not isinstance(test_item, type):
Benjamin Peterson847a4112010-03-14 15:04:17 +000092 @functools.wraps(test_item)
93 def skip_wrapper(*args, **kwargs):
94 raise SkipTest(reason)
95 test_item = skip_wrapper
96
97 test_item.__unittest_skip__ = True
98 test_item.__unittest_skip_why__ = reason
99 return test_item
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000100 return decorator
101
102def skipIf(condition, reason):
103 """
104 Skip a test if the condition is true.
105 """
106 if condition:
107 return skip(reason)
108 return _id
109
110def skipUnless(condition, reason):
111 """
112 Skip a test unless the condition is true.
113 """
114 if not condition:
115 return skip(reason)
116 return _id
117
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100118def expectedFailure(test_item):
119 test_item.__unittest_expecting_failure__ = True
120 return test_item
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000121
Serhiy Storchaka041dd8e2015-05-21 20:15:40 +0300122def _is_subtype(expected, basetype):
123 if isinstance(expected, tuple):
124 return all(_is_subtype(e, basetype) for e in expected)
125 return isinstance(expected, type) and issubclass(expected, basetype)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000126
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200127class _BaseTestCaseContext:
128
129 def __init__(self, test_case):
130 self.test_case = test_case
131
132 def _raiseFailure(self, standardMsg):
133 msg = self.test_case._formatMessage(self.msg, standardMsg)
134 raise self.test_case.failureException(msg)
135
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200136class _AssertRaisesBaseContext(_BaseTestCaseContext):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000137
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300138 def __init__(self, expected, test_case, expected_regex=None):
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200139 _BaseTestCaseContext.__init__(self, test_case)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000140 self.expected = expected
Ezio Melottib4dc2502011-05-06 15:01:41 +0300141 self.test_case = test_case
R David Murrayef1c2672014-03-25 15:31:50 -0400142 if expected_regex is not None:
Ezio Melottied3a7d22010-12-01 02:32:32 +0000143 expected_regex = re.compile(expected_regex)
144 self.expected_regex = expected_regex
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300145 self.obj_name = None
Ezio Melottib4dc2502011-05-06 15:01:41 +0300146 self.msg = None
147
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300148 def handle(self, name, args, kwargs):
Ezio Melottib4dc2502011-05-06 15:01:41 +0300149 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300150 If args is empty, assertRaises/Warns is being used as a
Ezio Melottib4dc2502011-05-06 15:01:41 +0300151 context manager, so check for a 'msg' kwarg and return self.
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300152 If args is not empty, call a callable passing positional and keyword
153 arguments.
Ezio Melottib4dc2502011-05-06 15:01:41 +0300154 """
Serhiy Storchaka041dd8e2015-05-21 20:15:40 +0300155 if not _is_subtype(self.expected, self._base_type):
156 raise TypeError('%s() arg 1 must be %s' %
157 (name, self._base_type_str))
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300158 if args and args[0] is None:
159 warnings.warn("callable is None",
160 DeprecationWarning, 3)
161 args = ()
162 if not args:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300163 self.msg = kwargs.pop('msg', None)
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300164 if kwargs:
165 warnings.warn('%r is an invalid keyword argument for '
166 'this function' % next(iter(kwargs)),
167 DeprecationWarning, 3)
Ezio Melottib4dc2502011-05-06 15:01:41 +0300168 return self
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300169
170 callable_obj, *args = args
171 try:
172 self.obj_name = callable_obj.__name__
173 except AttributeError:
174 self.obj_name = str(callable_obj)
Ezio Melottib4dc2502011-05-06 15:01:41 +0300175 with self:
176 callable_obj(*args, **kwargs)
177
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000178
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000179class _AssertRaisesContext(_AssertRaisesBaseContext):
180 """A context manager used to implement TestCase.assertRaises* methods."""
181
Serhiy Storchaka041dd8e2015-05-21 20:15:40 +0300182 _base_type = BaseException
183 _base_type_str = 'an exception type or tuple of exception types'
184
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000185 def __enter__(self):
Ezio Melotti49008232010-02-08 21:57:48 +0000186 return self
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000187
188 def __exit__(self, exc_type, exc_value, tb):
189 if exc_type is None:
190 try:
191 exc_name = self.expected.__name__
192 except AttributeError:
193 exc_name = str(self.expected)
194 if self.obj_name:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300195 self._raiseFailure("{} not raised by {}".format(exc_name,
196 self.obj_name))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000197 else:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300198 self._raiseFailure("{} not raised".format(exc_name))
Antoine Pitrou96810222014-04-29 01:23:50 +0200199 else:
200 traceback.clear_frames(tb)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000201 if not issubclass(exc_type, self.expected):
202 # let unexpected exceptions pass through
203 return False
Ezio Melotti49008232010-02-08 21:57:48 +0000204 # store exception, without traceback, for later retrieval
205 self.exception = exc_value.with_traceback(None)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000206 if self.expected_regex is None:
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000207 return True
208
Ezio Melottied3a7d22010-12-01 02:32:32 +0000209 expected_regex = self.expected_regex
210 if not expected_regex.search(str(exc_value)):
Ezio Melottib4dc2502011-05-06 15:01:41 +0300211 self._raiseFailure('"{}" does not match "{}"'.format(
212 expected_regex.pattern, str(exc_value)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000213 return True
214
215
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000216class _AssertWarnsContext(_AssertRaisesBaseContext):
217 """A context manager used to implement TestCase.assertWarns* methods."""
218
Serhiy Storchaka041dd8e2015-05-21 20:15:40 +0300219 _base_type = Warning
220 _base_type_str = 'a warning type or tuple of warning types'
221
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000222 def __enter__(self):
223 # The __warningregistry__'s need to be in a pristine state for tests
224 # to work properly.
225 for v in sys.modules.values():
226 if getattr(v, '__warningregistry__', None):
227 v.__warningregistry__ = {}
228 self.warnings_manager = warnings.catch_warnings(record=True)
229 self.warnings = self.warnings_manager.__enter__()
230 warnings.simplefilter("always", self.expected)
231 return self
232
233 def __exit__(self, exc_type, exc_value, tb):
234 self.warnings_manager.__exit__(exc_type, exc_value, tb)
235 if exc_type is not None:
236 # let unexpected exceptions pass through
237 return
238 try:
239 exc_name = self.expected.__name__
240 except AttributeError:
241 exc_name = str(self.expected)
242 first_matching = None
243 for m in self.warnings:
244 w = m.message
245 if not isinstance(w, self.expected):
246 continue
247 if first_matching is None:
248 first_matching = w
Ezio Melottied3a7d22010-12-01 02:32:32 +0000249 if (self.expected_regex is not None and
250 not self.expected_regex.search(str(w))):
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000251 continue
252 # store warning for later retrieval
253 self.warning = w
254 self.filename = m.filename
255 self.lineno = m.lineno
256 return
257 # Now we simply try to choose a helpful failure message
258 if first_matching is not None:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300259 self._raiseFailure('"{}" does not match "{}"'.format(
260 self.expected_regex.pattern, str(first_matching)))
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000261 if self.obj_name:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300262 self._raiseFailure("{} not triggered by {}".format(exc_name,
263 self.obj_name))
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000264 else:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300265 self._raiseFailure("{} not triggered".format(exc_name))
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000266
267
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200268
269_LoggingWatcher = collections.namedtuple("_LoggingWatcher",
270 ["records", "output"])
271
272
273class _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
292class _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
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000336class TestCase(object):
337 """A class whose instances are single test cases.
338
339 By default, the test code itself should be placed in a method named
340 'runTest'.
341
342 If the fixture may be used for many test cases, create as
343 many test methods as are needed. When instantiating such a TestCase
344 subclass, specify in the constructor arguments the name of the test method
345 that the instance is to execute.
346
347 Test authors should subclass TestCase for their own tests. Construction
348 and deconstruction of the test's environment ('fixture') can be
349 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
350
351 If it is necessary to override the __init__ method, the base class
352 __init__ method must always be called. It is important that subclasses
353 should not change the signature of their __init__ method, since instances
354 of the classes are instantiated automatically by parts of the framework
355 in order to be run.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000356
Ezio Melotti31797e52013-03-29 03:42:29 +0200357 When subclassing TestCase, you can set these attributes:
358 * failureException: determines which exception will be raised when
359 the instance's assertion methods fail; test methods raising this
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 """
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000368
369 failureException = AssertionError
370
Michael Foord5074df62010-12-03 00:53:09 +0000371 longMessage = True
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000372
Michael Foord085dfd32010-06-05 12:17:02 +0000373 maxDiff = 80*8
374
Ezio Melottiedd117f2011-04-27 10:20:38 +0300375 # If a string is longer than _diffThreshold, use normal comparison instead
376 # of difflib. See #11763.
377 _diffThreshold = 2**16
378
Benjamin Peterson847a4112010-03-14 15:04:17 +0000379 # Attribute used by TestSuite for classSetUp
380
381 _classSetupFailed = False
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000382
383 def __init__(self, methodName='runTest'):
384 """Create an instance of the class that will use the named test
385 method when executed. Raises a ValueError if the instance does
386 not have a method with the specified name.
387 """
388 self._testMethodName = methodName
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100389 self._outcome = None
Michael Foord32e1d832011-01-03 17:00:11 +0000390 self._testMethodDoc = 'No test'
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000391 try:
392 testMethod = getattr(self, methodName)
393 except AttributeError:
Michael Foord32e1d832011-01-03 17:00:11 +0000394 if methodName != 'runTest':
395 # we allow instantiation with no explicit method name
396 # but not an *incorrect* or missing method name
397 raise ValueError("no such test method in %s: %s" %
398 (self.__class__, methodName))
399 else:
400 self._testMethodDoc = testMethod.__doc__
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000401 self._cleanups = []
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100402 self._subtest = None
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000403
404 # Map types to custom assertEqual functions that will compare
405 # instances of said type in more detail to generate a more useful
406 # error message.
Benjamin Peterson34b2b262011-07-12 19:21:42 -0500407 self._type_equality_funcs = {}
Michael Foord8ca6d982010-11-20 15:34:26 +0000408 self.addTypeEqualityFunc(dict, 'assertDictEqual')
409 self.addTypeEqualityFunc(list, 'assertListEqual')
410 self.addTypeEqualityFunc(tuple, 'assertTupleEqual')
411 self.addTypeEqualityFunc(set, 'assertSetEqual')
412 self.addTypeEqualityFunc(frozenset, 'assertSetEqual')
413 self.addTypeEqualityFunc(str, 'assertMultiLineEqual')
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000414
415 def addTypeEqualityFunc(self, typeobj, function):
416 """Add a type specific assertEqual style function to compare a type.
417
418 This method is for use by TestCase subclasses that need to register
419 their own type equality functions to provide nicer error messages.
420
421 Args:
422 typeobj: The data type to call this function on when both values
423 are of the same type in assertEqual().
424 function: The callable taking two arguments and an optional
425 msg= argument that raises self.failureException with a
426 useful error message when the two arguments are not equal.
427 """
Benjamin Peterson8f326b22009-12-13 02:10:36 +0000428 self._type_equality_funcs[typeobj] = function
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000429
430 def addCleanup(self, function, *args, **kwargs):
431 """Add a function, with arguments, to be called when the test is
432 completed. Functions added are called on a LIFO basis and are
433 called after tearDown on test failure or success.
434
435 Cleanup items are called even if setUp fails (unlike tearDown)."""
436 self._cleanups.append((function, args, kwargs))
437
438 def setUp(self):
439 "Hook method for setting up the test fixture before exercising it."
440 pass
441
442 def tearDown(self):
443 "Hook method for deconstructing the test fixture after testing it."
444 pass
445
Benjamin Peterson847a4112010-03-14 15:04:17 +0000446 @classmethod
447 def setUpClass(cls):
448 "Hook method for setting up class fixture before running tests in the class."
449
450 @classmethod
451 def tearDownClass(cls):
452 "Hook method for deconstructing the class fixture after running all tests in the class."
453
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000454 def countTestCases(self):
455 return 1
456
457 def defaultTestResult(self):
458 return result.TestResult()
459
460 def shortDescription(self):
Michael Foord34c94622010-02-10 15:51:42 +0000461 """Returns a one-line description of the test, or None if no
462 description has been provided.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000463
Michael Foord34c94622010-02-10 15:51:42 +0000464 The default implementation of this method returns the first line of
465 the specified test method's docstring.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000466 """
Michael Foord34c94622010-02-10 15:51:42 +0000467 doc = self._testMethodDoc
468 return doc and doc.split("\n")[0].strip() or None
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000469
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000470
471 def id(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000472 return "%s.%s" % (strclass(self.__class__), self._testMethodName)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000473
474 def __eq__(self, other):
475 if type(self) is not type(other):
476 return NotImplemented
477
478 return self._testMethodName == other._testMethodName
479
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000480 def __hash__(self):
481 return hash((type(self), self._testMethodName))
482
483 def __str__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000484 return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000485
486 def __repr__(self):
487 return "<%s testMethod=%s>" % \
Benjamin Peterson847a4112010-03-14 15:04:17 +0000488 (strclass(self.__class__), self._testMethodName)
489
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100490 def _addSkip(self, result, test_case, reason):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000491 addSkip = getattr(result, 'addSkip', None)
492 if addSkip is not None:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100493 addSkip(test_case, reason)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000494 else:
495 warnings.warn("TestResult has no addSkip method, skips not reported",
496 RuntimeWarning, 2)
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100497 result.addSuccess(test_case)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000498
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100499 @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)
Michael Foordb3468f72010-12-19 03:19:47 +0000516 try:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100517 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, reporting as passes",
545 RuntimeWarning)
546 result.addSuccess(self)
547 else:
548 addExpectedFailure(self, exc_info)
549
550 def _addUnexpectedSuccess(self, result):
551 try:
552 addUnexpectedSuccess = result.addUnexpectedSuccess
553 except AttributeError:
554 warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failure",
555 RuntimeWarning)
556 # We need to pass an actual exception and traceback to addFailure,
557 # otherwise the legacy result can choke.
558 try:
559 raise _UnexpectedSuccess from None
560 except _UnexpectedSuccess:
561 result.addFailure(self, sys.exc_info())
562 else:
563 addUnexpectedSuccess(self)
Michael Foordb3468f72010-12-19 03:19:47 +0000564
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000565 def run(self, result=None):
566 orig_result = result
567 if result is None:
568 result = self.defaultTestResult()
569 startTestRun = getattr(result, 'startTestRun', None)
570 if startTestRun is not None:
571 startTestRun()
572
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000573 result.startTest(self)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000574
575 testMethod = getattr(self, self._testMethodName)
576 if (getattr(self.__class__, "__unittest_skip__", False) or
577 getattr(testMethod, "__unittest_skip__", False)):
578 # If the class or method was skipped.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000579 try:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000580 skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
581 or getattr(testMethod, '__unittest_skip_why__', ''))
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100582 self._addSkip(result, self, skip_why)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000583 finally:
584 result.stopTest(self)
585 return
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100586 expecting_failure = getattr(testMethod,
587 "__unittest_expecting_failure__", False)
Victor Stinner031bd532013-12-09 01:52:50 +0100588 outcome = _Outcome(result)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000589 try:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100590 self._outcome = outcome
Michael Foordb3468f72010-12-19 03:19:47 +0000591
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100592 with outcome.testPartExecutor(self):
593 self.setUp()
Michael Foordb3468f72010-12-19 03:19:47 +0000594 if outcome.success:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100595 outcome.expecting_failure = expecting_failure
596 with outcome.testPartExecutor(self, isTest=True):
597 testMethod()
598 outcome.expecting_failure = False
599 with outcome.testPartExecutor(self):
600 self.tearDown()
Michael Foordb3468f72010-12-19 03:19:47 +0000601
602 self.doCleanups()
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100603 for test, reason in outcome.skipped:
604 self._addSkip(result, test, reason)
605 self._feedErrorsToResult(result, outcome.errors)
Michael Foordb3468f72010-12-19 03:19:47 +0000606 if outcome.success:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100607 if expecting_failure:
608 if outcome.expectedFailure:
609 self._addExpectedFailure(result, outcome.expectedFailure)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000610 else:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100611 self._addUnexpectedSuccess(result)
612 else:
613 result.addSuccess(self)
Michael Foord1341bb02011-03-14 19:01:46 -0400614 return result
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000615 finally:
616 result.stopTest(self)
617 if orig_result is None:
618 stopTestRun = getattr(result, 'stopTestRun', None)
619 if stopTestRun is not None:
620 stopTestRun()
621
Victor Stinner031bd532013-12-09 01:52:50 +0100622 # explicitly break reference cycles:
623 # outcome.errors -> frame -> outcome -> outcome.errors
624 # outcome.expectedFailure -> frame -> outcome -> outcome.expectedFailure
625 outcome.errors.clear()
626 outcome.expectedFailure = None
627
628 # clear the outcome, no more needed
629 self._outcome = None
630
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000631 def doCleanups(self):
632 """Execute all cleanup functions. Normally called for you after
633 tearDown."""
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100634 outcome = self._outcome or _Outcome()
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000635 while self._cleanups:
Michael Foordb3468f72010-12-19 03:19:47 +0000636 function, args, kwargs = self._cleanups.pop()
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100637 with outcome.testPartExecutor(self):
638 function(*args, **kwargs)
Michael Foordb3468f72010-12-19 03:19:47 +0000639
640 # return this for backwards compatibility
641 # even though we no longer us it internally
642 return outcome.success
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000643
644 def __call__(self, *args, **kwds):
645 return self.run(*args, **kwds)
646
647 def debug(self):
648 """Run the test without collecting errors in a TestResult"""
649 self.setUp()
650 getattr(self, self._testMethodName)()
651 self.tearDown()
Michael Foordb8748742010-06-10 16:16:08 +0000652 while self._cleanups:
653 function, args, kwargs = self._cleanups.pop(-1)
654 function(*args, **kwargs)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000655
656 def skipTest(self, reason):
657 """Skip this test."""
658 raise SkipTest(reason)
659
660 def fail(self, msg=None):
661 """Fail immediately, with the given message."""
662 raise self.failureException(msg)
663
664 def assertFalse(self, expr, msg=None):
Ezio Melotti3044fa72010-12-18 17:31:58 +0000665 """Check that the expression is false."""
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000666 if expr:
Ezio Melotti3044fa72010-12-18 17:31:58 +0000667 msg = self._formatMessage(msg, "%s is not false" % safe_repr(expr))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000668 raise self.failureException(msg)
669
670 def assertTrue(self, expr, msg=None):
Ezio Melotti3044fa72010-12-18 17:31:58 +0000671 """Check that the expression is true."""
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000672 if not expr:
Ezio Melotti3044fa72010-12-18 17:31:58 +0000673 msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000674 raise self.failureException(msg)
675
676 def _formatMessage(self, msg, standardMsg):
677 """Honour the longMessage attribute when generating failure messages.
678 If longMessage is False this means:
679 * Use only an explicit message if it is provided
680 * Otherwise use the standard message for the assert
681
682 If longMessage is True:
683 * Use the standard message
684 * If an explicit message is provided, plus ' : ' and the explicit message
685 """
686 if not self.longMessage:
687 return msg or standardMsg
688 if msg is None:
689 return standardMsg
Benjamin Peterson847a4112010-03-14 15:04:17 +0000690 try:
691 # don't switch to '{}' formatting in Python 2.X
692 # it changes the way unicode input is handled
693 return '%s : %s' % (standardMsg, msg)
694 except UnicodeDecodeError:
695 return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000696
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300697 def assertRaises(self, expected_exception, *args, **kwargs):
698 """Fail unless an exception of class expected_exception is raised
699 by the callable when invoked with specified positional and
700 keyword arguments. If a different type of exception is
Andrew Svetlov737fb892012-12-18 21:14:22 +0200701 raised, it will not be caught, and the test case will be
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000702 deemed to have suffered an error, exactly as for an
703 unexpected exception.
704
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300705 If called with the callable and arguments omitted, will return a
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000706 context object used like this::
707
Michael Foord1c42b122010-02-05 22:58:21 +0000708 with self.assertRaises(SomeException):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000709 do_something()
Michael Foord1c42b122010-02-05 22:58:21 +0000710
Ezio Melottib4dc2502011-05-06 15:01:41 +0300711 An optional keyword argument 'msg' can be provided when assertRaises
712 is used as a context object.
713
Michael Foord1c42b122010-02-05 22:58:21 +0000714 The context manager keeps a reference to the exception as
Ezio Melotti49008232010-02-08 21:57:48 +0000715 the 'exception' attribute. This allows you to inspect the
Michael Foord1c42b122010-02-05 22:58:21 +0000716 exception after the assertion::
717
718 with self.assertRaises(SomeException) as cm:
719 do_something()
Ezio Melotti49008232010-02-08 21:57:48 +0000720 the_exception = cm.exception
Michael Foordb57ac6d2010-02-05 23:26:29 +0000721 self.assertEqual(the_exception.error_code, 3)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000722 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300723 context = _AssertRaisesContext(expected_exception, self)
724 return context.handle('assertRaises', args, kwargs)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000725
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300726 def assertWarns(self, expected_warning, *args, **kwargs):
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000727 """Fail unless a warning of class warnClass is triggered
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300728 by the callable when invoked with specified positional and
729 keyword arguments. If a different type of warning is
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000730 triggered, it will not be handled: depending on the other
731 warning filtering rules in effect, it might be silenced, printed
732 out, or raised as an exception.
733
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300734 If called with the callable and arguments omitted, will return a
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000735 context object used like this::
736
737 with self.assertWarns(SomeWarning):
738 do_something()
739
Ezio Melottib4dc2502011-05-06 15:01:41 +0300740 An optional keyword argument 'msg' can be provided when assertWarns
741 is used as a context object.
742
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000743 The context manager keeps a reference to the first matching
744 warning as the 'warning' attribute; similarly, the 'filename'
745 and 'lineno' attributes give you information about the line
746 of Python code from which the warning was triggered.
747 This allows you to inspect the warning after the assertion::
748
749 with self.assertWarns(SomeWarning) as cm:
750 do_something()
751 the_warning = cm.warning
752 self.assertEqual(the_warning.some_attribute, 147)
753 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300754 context = _AssertWarnsContext(expected_warning, self)
755 return context.handle('assertWarns', args, kwargs)
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000756
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200757 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)
778
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000779 def _getAssertEqualityFunc(self, first, second):
780 """Get a detailed comparison function for the types of the two args.
781
782 Returns: A callable accepting (first, second, msg=None) that will
783 raise a failure exception if first != second with a useful human
784 readable error message for those types.
785 """
786 #
787 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
788 # and vice versa. I opted for the conservative approach in case
789 # subclasses are not intended to be compared in detail to their super
790 # class instances using a type equality func. This means testing
791 # subtypes won't automagically use the detailed comparison. Callers
792 # should use their type specific assertSpamEqual method to compare
793 # subclasses if the detailed comparison is desired and appropriate.
794 # See the discussion in http://bugs.python.org/issue2578.
795 #
796 if type(first) is type(second):
797 asserter = self._type_equality_funcs.get(type(first))
798 if asserter is not None:
Benjamin Peterson34b2b262011-07-12 19:21:42 -0500799 if isinstance(asserter, str):
800 asserter = getattr(self, asserter)
Benjamin Peterson8f326b22009-12-13 02:10:36 +0000801 return asserter
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000802
803 return self._baseAssertEqual
804
805 def _baseAssertEqual(self, first, second, msg=None):
806 """The default assertEqual implementation, not type specific."""
807 if not first == second:
Serhiy Storchaka77622f52013-09-23 23:07:00 +0300808 standardMsg = '%s != %s' % _common_shorten_repr(first, second)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000809 msg = self._formatMessage(msg, standardMsg)
810 raise self.failureException(msg)
811
812 def assertEqual(self, first, second, msg=None):
813 """Fail if the two objects are unequal as determined by the '=='
814 operator.
815 """
816 assertion_func = self._getAssertEqualityFunc(first, second)
817 assertion_func(first, second, msg=msg)
818
819 def assertNotEqual(self, first, second, msg=None):
Ezio Melotti90eea972012-11-08 11:08:39 +0200820 """Fail if the two objects are equal as determined by the '!='
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000821 operator.
822 """
823 if not first != second:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000824 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
825 safe_repr(second)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000826 raise self.failureException(msg)
827
Michael Foord321d0592010-11-02 13:44:51 +0000828 def assertAlmostEqual(self, first, second, places=None, msg=None,
Benjamin Petersonb48af542010-04-11 20:43:16 +0000829 delta=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000830 """Fail if the two objects are unequal as determined by their
831 difference rounded to the given number of decimal places
Benjamin Petersonb48af542010-04-11 20:43:16 +0000832 (default 7) and comparing to zero, or by comparing that the
833 between the two objects is more than the given delta.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000834
835 Note that decimal places (from zero) are usually not the same
836 as significant digits (measured from the most signficant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000837
838 If the two objects compare equal then they will automatically
839 compare almost equal.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000840 """
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000841 if first == second:
Benjamin Petersonb48af542010-04-11 20:43:16 +0000842 # shortcut
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000843 return
Benjamin Petersonb48af542010-04-11 20:43:16 +0000844 if delta is not None and places is not None:
845 raise TypeError("specify delta or places not both")
846
847 if delta is not None:
848 if abs(first - second) <= delta:
849 return
850
851 standardMsg = '%s != %s within %s delta' % (safe_repr(first),
852 safe_repr(second),
853 safe_repr(delta))
854 else:
855 if places is None:
856 places = 7
857
858 if round(abs(second-first), places) == 0:
859 return
860
Benjamin Peterson847a4112010-03-14 15:04:17 +0000861 standardMsg = '%s != %s within %r places' % (safe_repr(first),
862 safe_repr(second),
863 places)
Benjamin Petersonb48af542010-04-11 20:43:16 +0000864 msg = self._formatMessage(msg, standardMsg)
865 raise self.failureException(msg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000866
Michael Foord321d0592010-11-02 13:44:51 +0000867 def assertNotAlmostEqual(self, first, second, places=None, msg=None,
Benjamin Petersonb48af542010-04-11 20:43:16 +0000868 delta=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000869 """Fail if the two objects are equal as determined by their
870 difference rounded to the given number of decimal places
Benjamin Petersonb48af542010-04-11 20:43:16 +0000871 (default 7) and comparing to zero, or by comparing that the
872 between the two objects is less than the given delta.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000873
874 Note that decimal places (from zero) are usually not the same
875 as significant digits (measured from the most signficant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000876
877 Objects that are equal automatically fail.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000878 """
Benjamin Petersonb48af542010-04-11 20:43:16 +0000879 if delta is not None and places is not None:
880 raise TypeError("specify delta or places not both")
881 if delta is not None:
882 if not (first == second) and abs(first - second) > delta:
883 return
884 standardMsg = '%s == %s within %s delta' % (safe_repr(first),
885 safe_repr(second),
886 safe_repr(delta))
887 else:
888 if places is None:
889 places = 7
890 if not (first == second) and round(abs(second-first), places) != 0:
891 return
Benjamin Peterson847a4112010-03-14 15:04:17 +0000892 standardMsg = '%s == %s within %r places' % (safe_repr(first),
Benjamin Petersonb48af542010-04-11 20:43:16 +0000893 safe_repr(second),
894 places)
895
896 msg = self._formatMessage(msg, standardMsg)
897 raise self.failureException(msg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000898
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000899
Michael Foord085dfd32010-06-05 12:17:02 +0000900 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000901 """An equality assertion for ordered sequences (like lists and tuples).
902
R. David Murrayad13f222010-01-29 22:17:58 +0000903 For the purposes of this function, a valid ordered sequence type is one
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000904 which can be indexed, has a length, and has an equality operator.
905
906 Args:
907 seq1: The first sequence to compare.
908 seq2: The second sequence to compare.
909 seq_type: The expected datatype of the sequences, or None if no
910 datatype should be enforced.
911 msg: Optional message to use on failure instead of a list of
912 differences.
913 """
Benjamin Petersonb29614e2012-10-09 11:16:03 -0400914 if seq_type is not None:
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000915 seq_type_name = seq_type.__name__
916 if not isinstance(seq1, seq_type):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000917 raise self.failureException('First sequence is not a %s: %s'
918 % (seq_type_name, safe_repr(seq1)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000919 if not isinstance(seq2, seq_type):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000920 raise self.failureException('Second sequence is not a %s: %s'
921 % (seq_type_name, safe_repr(seq2)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000922 else:
923 seq_type_name = "sequence"
924
925 differing = None
926 try:
927 len1 = len(seq1)
928 except (TypeError, NotImplementedError):
929 differing = 'First %s has no length. Non-sequence?' % (
930 seq_type_name)
931
932 if differing is None:
933 try:
934 len2 = len(seq2)
935 except (TypeError, NotImplementedError):
936 differing = 'Second %s has no length. Non-sequence?' % (
937 seq_type_name)
938
939 if differing is None:
940 if seq1 == seq2:
941 return
942
Serhiy Storchaka77622f52013-09-23 23:07:00 +0300943 differing = '%ss differ: %s != %s\n' % (
944 (seq_type_name.capitalize(),) +
945 _common_shorten_repr(seq1, seq2))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000946
947 for i in range(min(len1, len2)):
948 try:
949 item1 = seq1[i]
950 except (TypeError, IndexError, NotImplementedError):
951 differing += ('\nUnable to index element %d of first %s\n' %
952 (i, seq_type_name))
953 break
954
955 try:
956 item2 = seq2[i]
957 except (TypeError, IndexError, NotImplementedError):
958 differing += ('\nUnable to index element %d of second %s\n' %
959 (i, seq_type_name))
960 break
961
962 if item1 != item2:
963 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
964 (i, item1, item2))
965 break
966 else:
967 if (len1 == len2 and seq_type is None and
968 type(seq1) != type(seq2)):
969 # The sequences are the same, but have differing types.
970 return
971
972 if len1 > len2:
973 differing += ('\nFirst %s contains %d additional '
974 'elements.\n' % (seq_type_name, len1 - len2))
975 try:
976 differing += ('First extra element %d:\n%s\n' %
977 (len2, seq1[len2]))
978 except (TypeError, IndexError, NotImplementedError):
979 differing += ('Unable to index element %d '
980 'of first %s\n' % (len2, seq_type_name))
981 elif len1 < len2:
982 differing += ('\nSecond %s contains %d additional '
983 'elements.\n' % (seq_type_name, len2 - len1))
984 try:
985 differing += ('First extra element %d:\n%s\n' %
986 (len1, seq2[len1]))
987 except (TypeError, IndexError, NotImplementedError):
988 differing += ('Unable to index element %d '
989 'of second %s\n' % (len1, seq_type_name))
Michael Foord2034d9a2010-06-05 11:27:52 +0000990 standardMsg = differing
991 diffMsg = '\n' + '\n'.join(
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000992 difflib.ndiff(pprint.pformat(seq1).splitlines(),
993 pprint.pformat(seq2).splitlines()))
Michael Foord085dfd32010-06-05 12:17:02 +0000994
995 standardMsg = self._truncateMessage(standardMsg, diffMsg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000996 msg = self._formatMessage(msg, standardMsg)
997 self.fail(msg)
998
Michael Foord085dfd32010-06-05 12:17:02 +0000999 def _truncateMessage(self, message, diff):
1000 max_diff = self.maxDiff
1001 if max_diff is None or len(diff) <= max_diff:
1002 return message + diff
Michael Foord9dad32e2010-06-05 13:49:56 +00001003 return message + (DIFF_OMITTED % len(diff))
Michael Foord085dfd32010-06-05 12:17:02 +00001004
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001005 def assertListEqual(self, list1, list2, msg=None):
1006 """A list-specific equality assertion.
1007
1008 Args:
1009 list1: The first list to compare.
1010 list2: The second list to compare.
1011 msg: Optional message to use on failure instead of a list of
1012 differences.
1013
1014 """
1015 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
1016
1017 def assertTupleEqual(self, tuple1, tuple2, msg=None):
1018 """A tuple-specific equality assertion.
1019
1020 Args:
1021 tuple1: The first tuple to compare.
1022 tuple2: The second tuple to compare.
1023 msg: Optional message to use on failure instead of a list of
1024 differences.
1025 """
1026 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
1027
1028 def assertSetEqual(self, set1, set2, msg=None):
1029 """A set-specific equality assertion.
1030
1031 Args:
1032 set1: The first set to compare.
1033 set2: The second set to compare.
1034 msg: Optional message to use on failure instead of a list of
1035 differences.
1036
Michael Foord91c9da32010-03-20 17:21:27 +00001037 assertSetEqual uses ducktyping to support different types of sets, and
1038 is optimized for sets specifically (parameters must support a
1039 difference method).
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001040 """
1041 try:
1042 difference1 = set1.difference(set2)
1043 except TypeError as e:
1044 self.fail('invalid type when attempting set difference: %s' % e)
1045 except AttributeError as e:
1046 self.fail('first argument does not support set difference: %s' % e)
1047
1048 try:
1049 difference2 = set2.difference(set1)
1050 except TypeError as e:
1051 self.fail('invalid type when attempting set difference: %s' % e)
1052 except AttributeError as e:
1053 self.fail('second argument does not support set difference: %s' % e)
1054
1055 if not (difference1 or difference2):
1056 return
1057
1058 lines = []
1059 if difference1:
1060 lines.append('Items in the first set but not the second:')
1061 for item in difference1:
1062 lines.append(repr(item))
1063 if difference2:
1064 lines.append('Items in the second set but not the first:')
1065 for item in difference2:
1066 lines.append(repr(item))
1067
1068 standardMsg = '\n'.join(lines)
1069 self.fail(self._formatMessage(msg, standardMsg))
1070
1071 def assertIn(self, member, container, msg=None):
1072 """Just like self.assertTrue(a in b), but with a nicer default message."""
1073 if member not in container:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001074 standardMsg = '%s not found in %s' % (safe_repr(member),
1075 safe_repr(container))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001076 self.fail(self._formatMessage(msg, standardMsg))
1077
1078 def assertNotIn(self, member, container, msg=None):
1079 """Just like self.assertTrue(a not in b), but with a nicer default message."""
1080 if member in container:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001081 standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
1082 safe_repr(container))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001083 self.fail(self._formatMessage(msg, standardMsg))
1084
1085 def assertIs(self, expr1, expr2, msg=None):
1086 """Just like self.assertTrue(a is b), but with a nicer default message."""
1087 if expr1 is not expr2:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001088 standardMsg = '%s is not %s' % (safe_repr(expr1),
1089 safe_repr(expr2))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001090 self.fail(self._formatMessage(msg, standardMsg))
1091
1092 def assertIsNot(self, expr1, expr2, msg=None):
1093 """Just like self.assertTrue(a is not b), but with a nicer default message."""
1094 if expr1 is expr2:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001095 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001096 self.fail(self._formatMessage(msg, standardMsg))
1097
1098 def assertDictEqual(self, d1, d2, msg=None):
Ezio Melottib3aedd42010-11-20 19:04:17 +00001099 self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
1100 self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001101
1102 if d1 != d2:
Serhiy Storchaka77622f52013-09-23 23:07:00 +03001103 standardMsg = '%s != %s' % _common_shorten_repr(d1, d2)
Michael Foord085dfd32010-06-05 12:17:02 +00001104 diff = ('\n' + '\n'.join(difflib.ndiff(
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001105 pprint.pformat(d1).splitlines(),
1106 pprint.pformat(d2).splitlines())))
Michael Foordcb11b252010-06-05 13:14:43 +00001107 standardMsg = self._truncateMessage(standardMsg, diff)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001108 self.fail(self._formatMessage(msg, standardMsg))
1109
Ezio Melotti0f535012011-04-03 18:02:13 +03001110 def assertDictContainsSubset(self, subset, dictionary, msg=None):
1111 """Checks whether dictionary is a superset of subset."""
1112 warnings.warn('assertDictContainsSubset is deprecated',
1113 DeprecationWarning)
1114 missing = []
1115 mismatched = []
1116 for key, value in subset.items():
1117 if key not in dictionary:
1118 missing.append(key)
1119 elif value != dictionary[key]:
1120 mismatched.append('%s, expected: %s, actual: %s' %
1121 (safe_repr(key), safe_repr(value),
1122 safe_repr(dictionary[key])))
1123
1124 if not (missing or mismatched):
1125 return
1126
1127 standardMsg = ''
1128 if missing:
1129 standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
1130 missing)
1131 if mismatched:
1132 if standardMsg:
1133 standardMsg += '; '
1134 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
1135
1136 self.fail(self._formatMessage(msg, standardMsg))
1137
1138
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001139 def assertCountEqual(self, first, second, msg=None):
1140 """An unordered sequence comparison asserting that the same elements,
1141 regardless of order. If the same element occurs more than once,
1142 it verifies that the elements occur the same number of times.
Michael Foord8442a602010-03-20 16:58:04 +00001143
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001144 self.assertEqual(Counter(list(first)),
1145 Counter(list(second)))
Michael Foord8442a602010-03-20 16:58:04 +00001146
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001147 Example:
Michael Foord8442a602010-03-20 16:58:04 +00001148 - [0, 1, 1] and [1, 0, 1] compare equal.
1149 - [0, 0, 1] and [0, 1] compare unequal.
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001150
Michael Foord8442a602010-03-20 16:58:04 +00001151 """
Michael Foorde180d392011-01-28 19:51:48 +00001152 first_seq, second_seq = list(first), list(second)
Michael Foord8442a602010-03-20 16:58:04 +00001153 try:
Michael Foorde180d392011-01-28 19:51:48 +00001154 first = collections.Counter(first_seq)
1155 second = collections.Counter(second_seq)
Michael Foord8442a602010-03-20 16:58:04 +00001156 except TypeError:
Raymond Hettinger6518f5e2010-12-24 00:52:54 +00001157 # Handle case with unhashable elements
Michael Foorde180d392011-01-28 19:51:48 +00001158 differences = _count_diff_all_purpose(first_seq, second_seq)
Michael Foord8442a602010-03-20 16:58:04 +00001159 else:
Michael Foorde180d392011-01-28 19:51:48 +00001160 if first == second:
Raymond Hettinger6e165b32010-11-27 09:31:37 +00001161 return
Michael Foorde180d392011-01-28 19:51:48 +00001162 differences = _count_diff_hashable(first_seq, second_seq)
Michael Foord8442a602010-03-20 16:58:04 +00001163
Raymond Hettinger93e233d2010-12-24 10:02:22 +00001164 if differences:
1165 standardMsg = 'Element counts were not equal:\n'
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001166 lines = ['First has %d, Second has %d: %r' % diff for diff in differences]
Raymond Hettinger93e233d2010-12-24 10:02:22 +00001167 diffMsg = '\n'.join(lines)
1168 standardMsg = self._truncateMessage(standardMsg, diffMsg)
1169 msg = self._formatMessage(msg, standardMsg)
1170 self.fail(msg)
Michael Foord8442a602010-03-20 16:58:04 +00001171
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001172 def assertMultiLineEqual(self, first, second, msg=None):
1173 """Assert that two multi-line strings are equal."""
Ezio Melottib3aedd42010-11-20 19:04:17 +00001174 self.assertIsInstance(first, str, 'First argument is not a string')
1175 self.assertIsInstance(second, str, 'Second argument is not a string')
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001176
1177 if first != second:
Ezio Melottiedd117f2011-04-27 10:20:38 +03001178 # don't use difflib if the strings are too long
1179 if (len(first) > self._diffThreshold or
1180 len(second) > self._diffThreshold):
1181 self._baseAssertEqual(first, second, msg)
Ezio Melottid8b509b2011-09-28 17:37:55 +03001182 firstlines = first.splitlines(keepends=True)
1183 secondlines = second.splitlines(keepends=True)
Michael Foordc653ce32010-07-10 13:52:22 +00001184 if len(firstlines) == 1 and first.strip('\r\n') == first:
1185 firstlines = [first + '\n']
1186 secondlines = [second + '\n']
Serhiy Storchaka77622f52013-09-23 23:07:00 +03001187 standardMsg = '%s != %s' % _common_shorten_repr(first, second)
Michael Foordc653ce32010-07-10 13:52:22 +00001188 diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines))
Michael Foordcb11b252010-06-05 13:14:43 +00001189 standardMsg = self._truncateMessage(standardMsg, diff)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001190 self.fail(self._formatMessage(msg, standardMsg))
1191
1192 def assertLess(self, a, b, msg=None):
1193 """Just like self.assertTrue(a < b), but with a nicer default message."""
1194 if not a < b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001195 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001196 self.fail(self._formatMessage(msg, standardMsg))
1197
1198 def assertLessEqual(self, a, b, msg=None):
1199 """Just like self.assertTrue(a <= b), but with a nicer default message."""
1200 if not a <= b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001201 standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001202 self.fail(self._formatMessage(msg, standardMsg))
1203
1204 def assertGreater(self, a, b, msg=None):
1205 """Just like self.assertTrue(a > b), but with a nicer default message."""
1206 if not a > b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001207 standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001208 self.fail(self._formatMessage(msg, standardMsg))
1209
1210 def assertGreaterEqual(self, a, b, msg=None):
1211 """Just like self.assertTrue(a >= b), but with a nicer default message."""
1212 if not a >= b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001213 standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001214 self.fail(self._formatMessage(msg, standardMsg))
1215
1216 def assertIsNone(self, obj, msg=None):
1217 """Same as self.assertTrue(obj is None), with a nicer default message."""
1218 if obj is not None:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001219 standardMsg = '%s is not None' % (safe_repr(obj),)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001220 self.fail(self._formatMessage(msg, standardMsg))
1221
1222 def assertIsNotNone(self, obj, msg=None):
1223 """Included for symmetry with assertIsNone."""
1224 if obj is None:
1225 standardMsg = 'unexpectedly None'
1226 self.fail(self._formatMessage(msg, standardMsg))
1227
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001228 def assertIsInstance(self, obj, cls, msg=None):
1229 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
1230 default message."""
1231 if not isinstance(obj, cls):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001232 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001233 self.fail(self._formatMessage(msg, standardMsg))
1234
1235 def assertNotIsInstance(self, obj, cls, msg=None):
1236 """Included for symmetry with assertIsInstance."""
1237 if isinstance(obj, cls):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001238 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001239 self.fail(self._formatMessage(msg, standardMsg))
1240
Ezio Melottied3a7d22010-12-01 02:32:32 +00001241 def assertRaisesRegex(self, expected_exception, expected_regex,
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001242 *args, **kwargs):
Ezio Melottied3a7d22010-12-01 02:32:32 +00001243 """Asserts that the message in a raised exception matches a regex.
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001244
1245 Args:
1246 expected_exception: Exception class expected to be raised.
Ezio Melottied3a7d22010-12-01 02:32:32 +00001247 expected_regex: Regex (re pattern object or string) expected
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001248 to be found in error message.
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001249 args: Function to be called and extra positional args.
1250 kwargs: Extra kwargs.
Ezio Melottib4dc2502011-05-06 15:01:41 +03001251 msg: Optional message used in case of failure. Can only be used
1252 when assertRaisesRegex is used as a context manager.
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001253 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001254 context = _AssertRaisesContext(expected_exception, self, expected_regex)
1255 return context.handle('assertRaisesRegex', args, kwargs)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001256
Ezio Melottied3a7d22010-12-01 02:32:32 +00001257 def assertWarnsRegex(self, expected_warning, expected_regex,
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001258 *args, **kwargs):
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001259 """Asserts that the message in a triggered warning matches a regexp.
1260 Basic functioning is similar to assertWarns() with the addition
1261 that only warnings whose messages also match the regular expression
1262 are considered successful matches.
1263
1264 Args:
1265 expected_warning: Warning class expected to be triggered.
Ezio Melottied3a7d22010-12-01 02:32:32 +00001266 expected_regex: Regex (re pattern object or string) expected
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001267 to be found in error message.
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001268 args: Function to be called and extra positional args.
1269 kwargs: Extra kwargs.
Ezio Melottib4dc2502011-05-06 15:01:41 +03001270 msg: Optional message used in case of failure. Can only be used
1271 when assertWarnsRegex is used as a context manager.
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001272 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001273 context = _AssertWarnsContext(expected_warning, self, expected_regex)
1274 return context.handle('assertWarnsRegex', args, kwargs)
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001275
Ezio Melottied3a7d22010-12-01 02:32:32 +00001276 def assertRegex(self, text, expected_regex, msg=None):
Michael Foorde3ef5f12010-05-08 16:46:14 +00001277 """Fail the test unless the text matches the regular expression."""
Ezio Melottied3a7d22010-12-01 02:32:32 +00001278 if isinstance(expected_regex, (str, bytes)):
Gregory P. Smithed16bf42010-12-16 19:23:05 +00001279 assert expected_regex, "expected_regex must not be empty."
Ezio Melottied3a7d22010-12-01 02:32:32 +00001280 expected_regex = re.compile(expected_regex)
1281 if not expected_regex.search(text):
1282 msg = msg or "Regex didn't match"
1283 msg = '%s: %r not found in %r' % (msg, expected_regex.pattern, text)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001284 raise self.failureException(msg)
1285
Ezio Melotti8f776302010-12-10 02:32:05 +00001286 def assertNotRegex(self, text, unexpected_regex, msg=None):
Michael Foorde3ef5f12010-05-08 16:46:14 +00001287 """Fail the test if the text matches the regular expression."""
Ezio Melottied3a7d22010-12-01 02:32:32 +00001288 if isinstance(unexpected_regex, (str, bytes)):
1289 unexpected_regex = re.compile(unexpected_regex)
1290 match = unexpected_regex.search(text)
Benjamin Petersonb48af542010-04-11 20:43:16 +00001291 if match:
Ezio Melottied3a7d22010-12-01 02:32:32 +00001292 msg = msg or "Regex matched"
Benjamin Petersonb48af542010-04-11 20:43:16 +00001293 msg = '%s: %r matches %r in %r' % (msg,
1294 text[match.start():match.end()],
Ezio Melottied3a7d22010-12-01 02:32:32 +00001295 unexpected_regex.pattern,
Benjamin Petersonb48af542010-04-11 20:43:16 +00001296 text)
1297 raise self.failureException(msg)
1298
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001299
Ezio Melottied3a7d22010-12-01 02:32:32 +00001300 def _deprecate(original_func):
1301 def deprecated_func(*args, **kwargs):
1302 warnings.warn(
1303 'Please use {0} instead.'.format(original_func.__name__),
1304 DeprecationWarning, 2)
1305 return original_func(*args, **kwargs)
1306 return deprecated_func
1307
Ezio Melotti361467e2011-04-03 17:37:58 +03001308 # see #9424
Ezio Melotti0f535012011-04-03 18:02:13 +03001309 failUnlessEqual = assertEquals = _deprecate(assertEqual)
1310 failIfEqual = assertNotEquals = _deprecate(assertNotEqual)
1311 failUnlessAlmostEqual = assertAlmostEquals = _deprecate(assertAlmostEqual)
1312 failIfAlmostEqual = assertNotAlmostEquals = _deprecate(assertNotAlmostEqual)
1313 failUnless = assert_ = _deprecate(assertTrue)
1314 failUnlessRaises = _deprecate(assertRaises)
1315 failIf = _deprecate(assertFalse)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001316 assertRaisesRegexp = _deprecate(assertRaisesRegex)
1317 assertRegexpMatches = _deprecate(assertRegex)
1318
1319
1320
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001321class FunctionTestCase(TestCase):
1322 """A test case that wraps a test function.
1323
1324 This is useful for slipping pre-existing test functions into the
1325 unittest framework. Optionally, set-up and tidy-up functions can be
1326 supplied. As with TestCase, the tidy-up ('tearDown') function will
1327 always be called if the set-up ('setUp') function ran successfully.
1328 """
1329
1330 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
1331 super(FunctionTestCase, self).__init__()
1332 self._setUpFunc = setUp
1333 self._tearDownFunc = tearDown
1334 self._testFunc = testFunc
1335 self._description = description
1336
1337 def setUp(self):
1338 if self._setUpFunc is not None:
1339 self._setUpFunc()
1340
1341 def tearDown(self):
1342 if self._tearDownFunc is not None:
1343 self._tearDownFunc()
1344
1345 def runTest(self):
1346 self._testFunc()
1347
1348 def id(self):
1349 return self._testFunc.__name__
1350
1351 def __eq__(self, other):
1352 if not isinstance(other, self.__class__):
1353 return NotImplemented
1354
1355 return self._setUpFunc == other._setUpFunc and \
1356 self._tearDownFunc == other._tearDownFunc and \
1357 self._testFunc == other._testFunc and \
1358 self._description == other._description
1359
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001360 def __hash__(self):
1361 return hash((type(self), self._setUpFunc, self._tearDownFunc,
1362 self._testFunc, self._description))
1363
1364 def __str__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001365 return "%s (%s)" % (strclass(self.__class__),
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001366 self._testFunc.__name__)
1367
1368 def __repr__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001369 return "<%s tec=%s>" % (strclass(self.__class__),
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001370 self._testFunc)
1371
1372 def shortDescription(self):
1373 if self._description is not None:
1374 return self._description
1375 doc = self._testFunc.__doc__
1376 return doc and doc.split("\n")[0].strip() or None
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +01001377
1378
1379class _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())