blob: 524a7b1050469737a9942d4f3561d66a5eedc649 [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
Robert Collinsed599b72015-08-28 10:34:51 +1200586 expecting_failure_method = getattr(testMethod,
587 "__unittest_expecting_failure__", False)
588 expecting_failure_class = getattr(self,
589 "__unittest_expecting_failure__", False)
590 expecting_failure = expecting_failure_class or expecting_failure_method
Victor Stinner031bd532013-12-09 01:52:50 +0100591 outcome = _Outcome(result)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000592 try:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100593 self._outcome = outcome
Michael Foordb3468f72010-12-19 03:19:47 +0000594
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100595 with outcome.testPartExecutor(self):
596 self.setUp()
Michael Foordb3468f72010-12-19 03:19:47 +0000597 if outcome.success:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100598 outcome.expecting_failure = expecting_failure
599 with outcome.testPartExecutor(self, isTest=True):
600 testMethod()
601 outcome.expecting_failure = False
602 with outcome.testPartExecutor(self):
603 self.tearDown()
Michael Foordb3468f72010-12-19 03:19:47 +0000604
605 self.doCleanups()
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100606 for test, reason in outcome.skipped:
607 self._addSkip(result, test, reason)
608 self._feedErrorsToResult(result, outcome.errors)
Michael Foordb3468f72010-12-19 03:19:47 +0000609 if outcome.success:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100610 if expecting_failure:
611 if outcome.expectedFailure:
612 self._addExpectedFailure(result, outcome.expectedFailure)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000613 else:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100614 self._addUnexpectedSuccess(result)
615 else:
616 result.addSuccess(self)
Michael Foord1341bb02011-03-14 19:01:46 -0400617 return result
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000618 finally:
619 result.stopTest(self)
620 if orig_result is None:
621 stopTestRun = getattr(result, 'stopTestRun', None)
622 if stopTestRun is not None:
623 stopTestRun()
624
Victor Stinner031bd532013-12-09 01:52:50 +0100625 # explicitly break reference cycles:
626 # outcome.errors -> frame -> outcome -> outcome.errors
627 # outcome.expectedFailure -> frame -> outcome -> outcome.expectedFailure
628 outcome.errors.clear()
629 outcome.expectedFailure = None
630
631 # clear the outcome, no more needed
632 self._outcome = None
633
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000634 def doCleanups(self):
635 """Execute all cleanup functions. Normally called for you after
636 tearDown."""
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100637 outcome = self._outcome or _Outcome()
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000638 while self._cleanups:
Michael Foordb3468f72010-12-19 03:19:47 +0000639 function, args, kwargs = self._cleanups.pop()
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100640 with outcome.testPartExecutor(self):
641 function(*args, **kwargs)
Michael Foordb3468f72010-12-19 03:19:47 +0000642
643 # return this for backwards compatibility
644 # even though we no longer us it internally
645 return outcome.success
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000646
647 def __call__(self, *args, **kwds):
648 return self.run(*args, **kwds)
649
650 def debug(self):
651 """Run the test without collecting errors in a TestResult"""
652 self.setUp()
653 getattr(self, self._testMethodName)()
654 self.tearDown()
Michael Foordb8748742010-06-10 16:16:08 +0000655 while self._cleanups:
656 function, args, kwargs = self._cleanups.pop(-1)
657 function(*args, **kwargs)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000658
659 def skipTest(self, reason):
660 """Skip this test."""
661 raise SkipTest(reason)
662
663 def fail(self, msg=None):
664 """Fail immediately, with the given message."""
665 raise self.failureException(msg)
666
667 def assertFalse(self, expr, msg=None):
Ezio Melotti3044fa72010-12-18 17:31:58 +0000668 """Check that the expression is false."""
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000669 if expr:
Ezio Melotti3044fa72010-12-18 17:31:58 +0000670 msg = self._formatMessage(msg, "%s is not false" % safe_repr(expr))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000671 raise self.failureException(msg)
672
673 def assertTrue(self, expr, msg=None):
Ezio Melotti3044fa72010-12-18 17:31:58 +0000674 """Check that the expression is true."""
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000675 if not expr:
Ezio Melotti3044fa72010-12-18 17:31:58 +0000676 msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000677 raise self.failureException(msg)
678
679 def _formatMessage(self, msg, standardMsg):
680 """Honour the longMessage attribute when generating failure messages.
681 If longMessage is False this means:
682 * Use only an explicit message if it is provided
683 * Otherwise use the standard message for the assert
684
685 If longMessage is True:
686 * Use the standard message
687 * If an explicit message is provided, plus ' : ' and the explicit message
688 """
689 if not self.longMessage:
690 return msg or standardMsg
691 if msg is None:
692 return standardMsg
Benjamin Peterson847a4112010-03-14 15:04:17 +0000693 try:
694 # don't switch to '{}' formatting in Python 2.X
695 # it changes the way unicode input is handled
696 return '%s : %s' % (standardMsg, msg)
697 except UnicodeDecodeError:
698 return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000699
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300700 def assertRaises(self, expected_exception, *args, **kwargs):
701 """Fail unless an exception of class expected_exception is raised
702 by the callable when invoked with specified positional and
703 keyword arguments. If a different type of exception is
Andrew Svetlov737fb892012-12-18 21:14:22 +0200704 raised, it will not be caught, and the test case will be
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000705 deemed to have suffered an error, exactly as for an
706 unexpected exception.
707
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300708 If called with the callable and arguments omitted, will return a
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000709 context object used like this::
710
Michael Foord1c42b122010-02-05 22:58:21 +0000711 with self.assertRaises(SomeException):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000712 do_something()
Michael Foord1c42b122010-02-05 22:58:21 +0000713
Ezio Melottib4dc2502011-05-06 15:01:41 +0300714 An optional keyword argument 'msg' can be provided when assertRaises
715 is used as a context object.
716
Michael Foord1c42b122010-02-05 22:58:21 +0000717 The context manager keeps a reference to the exception as
Ezio Melotti49008232010-02-08 21:57:48 +0000718 the 'exception' attribute. This allows you to inspect the
Michael Foord1c42b122010-02-05 22:58:21 +0000719 exception after the assertion::
720
721 with self.assertRaises(SomeException) as cm:
722 do_something()
Ezio Melotti49008232010-02-08 21:57:48 +0000723 the_exception = cm.exception
Michael Foordb57ac6d2010-02-05 23:26:29 +0000724 self.assertEqual(the_exception.error_code, 3)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000725 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300726 context = _AssertRaisesContext(expected_exception, self)
727 return context.handle('assertRaises', args, kwargs)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000728
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300729 def assertWarns(self, expected_warning, *args, **kwargs):
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000730 """Fail unless a warning of class warnClass is triggered
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300731 by the callable when invoked with specified positional and
732 keyword arguments. If a different type of warning is
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000733 triggered, it will not be handled: depending on the other
734 warning filtering rules in effect, it might be silenced, printed
735 out, or raised as an exception.
736
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300737 If called with the callable and arguments omitted, will return a
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000738 context object used like this::
739
740 with self.assertWarns(SomeWarning):
741 do_something()
742
Ezio Melottib4dc2502011-05-06 15:01:41 +0300743 An optional keyword argument 'msg' can be provided when assertWarns
744 is used as a context object.
745
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000746 The context manager keeps a reference to the first matching
747 warning as the 'warning' attribute; similarly, the 'filename'
748 and 'lineno' attributes give you information about the line
749 of Python code from which the warning was triggered.
750 This allows you to inspect the warning after the assertion::
751
752 with self.assertWarns(SomeWarning) as cm:
753 do_something()
754 the_warning = cm.warning
755 self.assertEqual(the_warning.some_attribute, 147)
756 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300757 context = _AssertWarnsContext(expected_warning, self)
758 return context.handle('assertWarns', args, kwargs)
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000759
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200760 def assertLogs(self, logger=None, level=None):
761 """Fail unless a log message of level *level* or higher is emitted
762 on *logger_name* or its children. If omitted, *level* defaults to
763 INFO and *logger* defaults to the root logger.
764
765 This method must be used as a context manager, and will yield
766 a recording object with two attributes: `output` and `records`.
767 At the end of the context manager, the `output` attribute will
768 be a list of the matching formatted log messages and the
769 `records` attribute will be a list of the corresponding LogRecord
770 objects.
771
772 Example::
773
774 with self.assertLogs('foo', level='INFO') as cm:
775 logging.getLogger('foo').info('first message')
776 logging.getLogger('foo.bar').error('second message')
777 self.assertEqual(cm.output, ['INFO:foo:first message',
778 'ERROR:foo.bar:second message'])
779 """
780 return _AssertLogsContext(self, logger, level)
781
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000782 def _getAssertEqualityFunc(self, first, second):
783 """Get a detailed comparison function for the types of the two args.
784
785 Returns: A callable accepting (first, second, msg=None) that will
786 raise a failure exception if first != second with a useful human
787 readable error message for those types.
788 """
789 #
790 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
791 # and vice versa. I opted for the conservative approach in case
792 # subclasses are not intended to be compared in detail to their super
793 # class instances using a type equality func. This means testing
794 # subtypes won't automagically use the detailed comparison. Callers
795 # should use their type specific assertSpamEqual method to compare
796 # subclasses if the detailed comparison is desired and appropriate.
797 # See the discussion in http://bugs.python.org/issue2578.
798 #
799 if type(first) is type(second):
800 asserter = self._type_equality_funcs.get(type(first))
801 if asserter is not None:
Benjamin Peterson34b2b262011-07-12 19:21:42 -0500802 if isinstance(asserter, str):
803 asserter = getattr(self, asserter)
Benjamin Peterson8f326b22009-12-13 02:10:36 +0000804 return asserter
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000805
806 return self._baseAssertEqual
807
808 def _baseAssertEqual(self, first, second, msg=None):
809 """The default assertEqual implementation, not type specific."""
810 if not first == second:
Serhiy Storchaka77622f52013-09-23 23:07:00 +0300811 standardMsg = '%s != %s' % _common_shorten_repr(first, second)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000812 msg = self._formatMessage(msg, standardMsg)
813 raise self.failureException(msg)
814
815 def assertEqual(self, first, second, msg=None):
816 """Fail if the two objects are unequal as determined by the '=='
817 operator.
818 """
819 assertion_func = self._getAssertEqualityFunc(first, second)
820 assertion_func(first, second, msg=msg)
821
822 def assertNotEqual(self, first, second, msg=None):
Ezio Melotti90eea972012-11-08 11:08:39 +0200823 """Fail if the two objects are equal as determined by the '!='
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000824 operator.
825 """
826 if not first != second:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000827 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
828 safe_repr(second)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000829 raise self.failureException(msg)
830
Michael Foord321d0592010-11-02 13:44:51 +0000831 def assertAlmostEqual(self, first, second, places=None, msg=None,
Benjamin Petersonb48af542010-04-11 20:43:16 +0000832 delta=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000833 """Fail if the two objects are unequal as determined by their
834 difference rounded to the given number of decimal places
Benjamin Petersonb48af542010-04-11 20:43:16 +0000835 (default 7) and comparing to zero, or by comparing that the
836 between the two objects is more than the given delta.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000837
838 Note that decimal places (from zero) are usually not the same
839 as significant digits (measured from the most signficant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000840
841 If the two objects compare equal then they will automatically
842 compare almost equal.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000843 """
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000844 if first == second:
Benjamin Petersonb48af542010-04-11 20:43:16 +0000845 # shortcut
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000846 return
Benjamin Petersonb48af542010-04-11 20:43:16 +0000847 if delta is not None and places is not None:
848 raise TypeError("specify delta or places not both")
849
850 if delta is not None:
851 if abs(first - second) <= delta:
852 return
853
854 standardMsg = '%s != %s within %s delta' % (safe_repr(first),
855 safe_repr(second),
856 safe_repr(delta))
857 else:
858 if places is None:
859 places = 7
860
861 if round(abs(second-first), places) == 0:
862 return
863
Benjamin Peterson847a4112010-03-14 15:04:17 +0000864 standardMsg = '%s != %s within %r places' % (safe_repr(first),
865 safe_repr(second),
866 places)
Benjamin Petersonb48af542010-04-11 20:43:16 +0000867 msg = self._formatMessage(msg, standardMsg)
868 raise self.failureException(msg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000869
Michael Foord321d0592010-11-02 13:44:51 +0000870 def assertNotAlmostEqual(self, first, second, places=None, msg=None,
Benjamin Petersonb48af542010-04-11 20:43:16 +0000871 delta=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000872 """Fail if the two objects are equal as determined by their
873 difference rounded to the given number of decimal places
Benjamin Petersonb48af542010-04-11 20:43:16 +0000874 (default 7) and comparing to zero, or by comparing that the
875 between the two objects is less than the given delta.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000876
877 Note that decimal places (from zero) are usually not the same
878 as significant digits (measured from the most signficant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000879
880 Objects that are equal automatically fail.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000881 """
Benjamin Petersonb48af542010-04-11 20:43:16 +0000882 if delta is not None and places is not None:
883 raise TypeError("specify delta or places not both")
884 if delta is not None:
885 if not (first == second) and abs(first - second) > delta:
886 return
887 standardMsg = '%s == %s within %s delta' % (safe_repr(first),
888 safe_repr(second),
889 safe_repr(delta))
890 else:
891 if places is None:
892 places = 7
893 if not (first == second) and round(abs(second-first), places) != 0:
894 return
Benjamin Peterson847a4112010-03-14 15:04:17 +0000895 standardMsg = '%s == %s within %r places' % (safe_repr(first),
Benjamin Petersonb48af542010-04-11 20:43:16 +0000896 safe_repr(second),
897 places)
898
899 msg = self._formatMessage(msg, standardMsg)
900 raise self.failureException(msg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000901
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000902
Michael Foord085dfd32010-06-05 12:17:02 +0000903 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000904 """An equality assertion for ordered sequences (like lists and tuples).
905
R. David Murrayad13f222010-01-29 22:17:58 +0000906 For the purposes of this function, a valid ordered sequence type is one
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000907 which can be indexed, has a length, and has an equality operator.
908
909 Args:
910 seq1: The first sequence to compare.
911 seq2: The second sequence to compare.
912 seq_type: The expected datatype of the sequences, or None if no
913 datatype should be enforced.
914 msg: Optional message to use on failure instead of a list of
915 differences.
916 """
Benjamin Petersonb29614e2012-10-09 11:16:03 -0400917 if seq_type is not None:
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000918 seq_type_name = seq_type.__name__
919 if not isinstance(seq1, seq_type):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000920 raise self.failureException('First sequence is not a %s: %s'
921 % (seq_type_name, safe_repr(seq1)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000922 if not isinstance(seq2, seq_type):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000923 raise self.failureException('Second sequence is not a %s: %s'
924 % (seq_type_name, safe_repr(seq2)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000925 else:
926 seq_type_name = "sequence"
927
928 differing = None
929 try:
930 len1 = len(seq1)
931 except (TypeError, NotImplementedError):
932 differing = 'First %s has no length. Non-sequence?' % (
933 seq_type_name)
934
935 if differing is None:
936 try:
937 len2 = len(seq2)
938 except (TypeError, NotImplementedError):
939 differing = 'Second %s has no length. Non-sequence?' % (
940 seq_type_name)
941
942 if differing is None:
943 if seq1 == seq2:
944 return
945
Serhiy Storchaka77622f52013-09-23 23:07:00 +0300946 differing = '%ss differ: %s != %s\n' % (
947 (seq_type_name.capitalize(),) +
948 _common_shorten_repr(seq1, seq2))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000949
950 for i in range(min(len1, len2)):
951 try:
952 item1 = seq1[i]
953 except (TypeError, IndexError, NotImplementedError):
954 differing += ('\nUnable to index element %d of first %s\n' %
955 (i, seq_type_name))
956 break
957
958 try:
959 item2 = seq2[i]
960 except (TypeError, IndexError, NotImplementedError):
961 differing += ('\nUnable to index element %d of second %s\n' %
962 (i, seq_type_name))
963 break
964
965 if item1 != item2:
966 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
Serhiy Storchaka685fbed2016-04-25 08:58:25 +0300967 ((i,) + _common_shorten_repr(item1, item2)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000968 break
969 else:
970 if (len1 == len2 and seq_type is None and
971 type(seq1) != type(seq2)):
972 # The sequences are the same, but have differing types.
973 return
974
975 if len1 > len2:
976 differing += ('\nFirst %s contains %d additional '
977 'elements.\n' % (seq_type_name, len1 - len2))
978 try:
979 differing += ('First extra element %d:\n%s\n' %
Serhiy Storchaka685fbed2016-04-25 08:58:25 +0300980 (len2, safe_repr(seq1[len2])))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000981 except (TypeError, IndexError, NotImplementedError):
982 differing += ('Unable to index element %d '
983 'of first %s\n' % (len2, seq_type_name))
984 elif len1 < len2:
985 differing += ('\nSecond %s contains %d additional '
986 'elements.\n' % (seq_type_name, len2 - len1))
987 try:
988 differing += ('First extra element %d:\n%s\n' %
Serhiy Storchaka685fbed2016-04-25 08:58:25 +0300989 (len1, safe_repr(seq2[len1])))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000990 except (TypeError, IndexError, NotImplementedError):
991 differing += ('Unable to index element %d '
992 'of second %s\n' % (len1, seq_type_name))
Michael Foord2034d9a2010-06-05 11:27:52 +0000993 standardMsg = differing
994 diffMsg = '\n' + '\n'.join(
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000995 difflib.ndiff(pprint.pformat(seq1).splitlines(),
996 pprint.pformat(seq2).splitlines()))
Michael Foord085dfd32010-06-05 12:17:02 +0000997
998 standardMsg = self._truncateMessage(standardMsg, diffMsg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000999 msg = self._formatMessage(msg, standardMsg)
1000 self.fail(msg)
1001
Michael Foord085dfd32010-06-05 12:17:02 +00001002 def _truncateMessage(self, message, diff):
1003 max_diff = self.maxDiff
1004 if max_diff is None or len(diff) <= max_diff:
1005 return message + diff
Michael Foord9dad32e2010-06-05 13:49:56 +00001006 return message + (DIFF_OMITTED % len(diff))
Michael Foord085dfd32010-06-05 12:17:02 +00001007
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001008 def assertListEqual(self, list1, list2, msg=None):
1009 """A list-specific equality assertion.
1010
1011 Args:
1012 list1: The first list to compare.
1013 list2: The second list to compare.
1014 msg: Optional message to use on failure instead of a list of
1015 differences.
1016
1017 """
1018 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
1019
1020 def assertTupleEqual(self, tuple1, tuple2, msg=None):
1021 """A tuple-specific equality assertion.
1022
1023 Args:
1024 tuple1: The first tuple to compare.
1025 tuple2: The second tuple to compare.
1026 msg: Optional message to use on failure instead of a list of
1027 differences.
1028 """
1029 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
1030
1031 def assertSetEqual(self, set1, set2, msg=None):
1032 """A set-specific equality assertion.
1033
1034 Args:
1035 set1: The first set to compare.
1036 set2: The second set to compare.
1037 msg: Optional message to use on failure instead of a list of
1038 differences.
1039
Michael Foord91c9da32010-03-20 17:21:27 +00001040 assertSetEqual uses ducktyping to support different types of sets, and
1041 is optimized for sets specifically (parameters must support a
1042 difference method).
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001043 """
1044 try:
1045 difference1 = set1.difference(set2)
1046 except TypeError as e:
1047 self.fail('invalid type when attempting set difference: %s' % e)
1048 except AttributeError as e:
1049 self.fail('first argument does not support set difference: %s' % e)
1050
1051 try:
1052 difference2 = set2.difference(set1)
1053 except TypeError as e:
1054 self.fail('invalid type when attempting set difference: %s' % e)
1055 except AttributeError as e:
1056 self.fail('second argument does not support set difference: %s' % e)
1057
1058 if not (difference1 or difference2):
1059 return
1060
1061 lines = []
1062 if difference1:
1063 lines.append('Items in the first set but not the second:')
1064 for item in difference1:
1065 lines.append(repr(item))
1066 if difference2:
1067 lines.append('Items in the second set but not the first:')
1068 for item in difference2:
1069 lines.append(repr(item))
1070
1071 standardMsg = '\n'.join(lines)
1072 self.fail(self._formatMessage(msg, standardMsg))
1073
1074 def assertIn(self, member, container, msg=None):
1075 """Just like self.assertTrue(a in b), but with a nicer default message."""
1076 if member not in container:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001077 standardMsg = '%s not found in %s' % (safe_repr(member),
1078 safe_repr(container))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001079 self.fail(self._formatMessage(msg, standardMsg))
1080
1081 def assertNotIn(self, member, container, msg=None):
1082 """Just like self.assertTrue(a not in b), but with a nicer default message."""
1083 if member in container:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001084 standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
1085 safe_repr(container))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001086 self.fail(self._formatMessage(msg, standardMsg))
1087
1088 def assertIs(self, expr1, expr2, msg=None):
1089 """Just like self.assertTrue(a is b), but with a nicer default message."""
1090 if expr1 is not expr2:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001091 standardMsg = '%s is not %s' % (safe_repr(expr1),
1092 safe_repr(expr2))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001093 self.fail(self._formatMessage(msg, standardMsg))
1094
1095 def assertIsNot(self, expr1, expr2, msg=None):
1096 """Just like self.assertTrue(a is not b), but with a nicer default message."""
1097 if expr1 is expr2:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001098 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001099 self.fail(self._formatMessage(msg, standardMsg))
1100
1101 def assertDictEqual(self, d1, d2, msg=None):
Ezio Melottib3aedd42010-11-20 19:04:17 +00001102 self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
1103 self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001104
1105 if d1 != d2:
Serhiy Storchaka77622f52013-09-23 23:07:00 +03001106 standardMsg = '%s != %s' % _common_shorten_repr(d1, d2)
Michael Foord085dfd32010-06-05 12:17:02 +00001107 diff = ('\n' + '\n'.join(difflib.ndiff(
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001108 pprint.pformat(d1).splitlines(),
1109 pprint.pformat(d2).splitlines())))
Michael Foordcb11b252010-06-05 13:14:43 +00001110 standardMsg = self._truncateMessage(standardMsg, diff)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001111 self.fail(self._formatMessage(msg, standardMsg))
1112
Ezio Melotti0f535012011-04-03 18:02:13 +03001113 def assertDictContainsSubset(self, subset, dictionary, msg=None):
1114 """Checks whether dictionary is a superset of subset."""
1115 warnings.warn('assertDictContainsSubset is deprecated',
1116 DeprecationWarning)
1117 missing = []
1118 mismatched = []
1119 for key, value in subset.items():
1120 if key not in dictionary:
1121 missing.append(key)
1122 elif value != dictionary[key]:
1123 mismatched.append('%s, expected: %s, actual: %s' %
1124 (safe_repr(key), safe_repr(value),
1125 safe_repr(dictionary[key])))
1126
1127 if not (missing or mismatched):
1128 return
1129
1130 standardMsg = ''
1131 if missing:
1132 standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
1133 missing)
1134 if mismatched:
1135 if standardMsg:
1136 standardMsg += '; '
1137 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
1138
1139 self.fail(self._formatMessage(msg, standardMsg))
1140
1141
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001142 def assertCountEqual(self, first, second, msg=None):
1143 """An unordered sequence comparison asserting that the same elements,
1144 regardless of order. If the same element occurs more than once,
1145 it verifies that the elements occur the same number of times.
Michael Foord8442a602010-03-20 16:58:04 +00001146
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001147 self.assertEqual(Counter(list(first)),
1148 Counter(list(second)))
Michael Foord8442a602010-03-20 16:58:04 +00001149
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001150 Example:
Michael Foord8442a602010-03-20 16:58:04 +00001151 - [0, 1, 1] and [1, 0, 1] compare equal.
1152 - [0, 0, 1] and [0, 1] compare unequal.
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001153
Michael Foord8442a602010-03-20 16:58:04 +00001154 """
Michael Foorde180d392011-01-28 19:51:48 +00001155 first_seq, second_seq = list(first), list(second)
Michael Foord8442a602010-03-20 16:58:04 +00001156 try:
Michael Foorde180d392011-01-28 19:51:48 +00001157 first = collections.Counter(first_seq)
1158 second = collections.Counter(second_seq)
Michael Foord8442a602010-03-20 16:58:04 +00001159 except TypeError:
Raymond Hettinger6518f5e2010-12-24 00:52:54 +00001160 # Handle case with unhashable elements
Michael Foorde180d392011-01-28 19:51:48 +00001161 differences = _count_diff_all_purpose(first_seq, second_seq)
Michael Foord8442a602010-03-20 16:58:04 +00001162 else:
Michael Foorde180d392011-01-28 19:51:48 +00001163 if first == second:
Raymond Hettinger6e165b32010-11-27 09:31:37 +00001164 return
Michael Foorde180d392011-01-28 19:51:48 +00001165 differences = _count_diff_hashable(first_seq, second_seq)
Michael Foord8442a602010-03-20 16:58:04 +00001166
Raymond Hettinger93e233d2010-12-24 10:02:22 +00001167 if differences:
1168 standardMsg = 'Element counts were not equal:\n'
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001169 lines = ['First has %d, Second has %d: %r' % diff for diff in differences]
Raymond Hettinger93e233d2010-12-24 10:02:22 +00001170 diffMsg = '\n'.join(lines)
1171 standardMsg = self._truncateMessage(standardMsg, diffMsg)
1172 msg = self._formatMessage(msg, standardMsg)
1173 self.fail(msg)
Michael Foord8442a602010-03-20 16:58:04 +00001174
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001175 def assertMultiLineEqual(self, first, second, msg=None):
1176 """Assert that two multi-line strings are equal."""
Ezio Melottib3aedd42010-11-20 19:04:17 +00001177 self.assertIsInstance(first, str, 'First argument is not a string')
1178 self.assertIsInstance(second, str, 'Second argument is not a string')
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001179
1180 if first != second:
Ezio Melottiedd117f2011-04-27 10:20:38 +03001181 # don't use difflib if the strings are too long
1182 if (len(first) > self._diffThreshold or
1183 len(second) > self._diffThreshold):
1184 self._baseAssertEqual(first, second, msg)
Ezio Melottid8b509b2011-09-28 17:37:55 +03001185 firstlines = first.splitlines(keepends=True)
1186 secondlines = second.splitlines(keepends=True)
Michael Foordc653ce32010-07-10 13:52:22 +00001187 if len(firstlines) == 1 and first.strip('\r\n') == first:
1188 firstlines = [first + '\n']
1189 secondlines = [second + '\n']
Serhiy Storchaka77622f52013-09-23 23:07:00 +03001190 standardMsg = '%s != %s' % _common_shorten_repr(first, second)
Michael Foordc653ce32010-07-10 13:52:22 +00001191 diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines))
Michael Foordcb11b252010-06-05 13:14:43 +00001192 standardMsg = self._truncateMessage(standardMsg, diff)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001193 self.fail(self._formatMessage(msg, standardMsg))
1194
1195 def assertLess(self, a, b, msg=None):
1196 """Just like self.assertTrue(a < b), but with a nicer default message."""
1197 if not a < b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001198 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001199 self.fail(self._formatMessage(msg, standardMsg))
1200
1201 def assertLessEqual(self, a, b, msg=None):
1202 """Just like self.assertTrue(a <= b), but with a nicer default message."""
1203 if not a <= b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001204 standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001205 self.fail(self._formatMessage(msg, standardMsg))
1206
1207 def assertGreater(self, a, b, msg=None):
1208 """Just like self.assertTrue(a > b), but with a nicer default message."""
1209 if not a > b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001210 standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001211 self.fail(self._formatMessage(msg, standardMsg))
1212
1213 def assertGreaterEqual(self, a, b, msg=None):
1214 """Just like self.assertTrue(a >= b), but with a nicer default message."""
1215 if not a >= b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001216 standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001217 self.fail(self._formatMessage(msg, standardMsg))
1218
1219 def assertIsNone(self, obj, msg=None):
1220 """Same as self.assertTrue(obj is None), with a nicer default message."""
1221 if obj is not None:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001222 standardMsg = '%s is not None' % (safe_repr(obj),)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001223 self.fail(self._formatMessage(msg, standardMsg))
1224
1225 def assertIsNotNone(self, obj, msg=None):
1226 """Included for symmetry with assertIsNone."""
1227 if obj is None:
1228 standardMsg = 'unexpectedly None'
1229 self.fail(self._formatMessage(msg, standardMsg))
1230
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001231 def assertIsInstance(self, obj, cls, msg=None):
1232 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
1233 default message."""
1234 if not isinstance(obj, cls):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001235 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001236 self.fail(self._formatMessage(msg, standardMsg))
1237
1238 def assertNotIsInstance(self, obj, cls, msg=None):
1239 """Included for symmetry with assertIsInstance."""
1240 if isinstance(obj, cls):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001241 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001242 self.fail(self._formatMessage(msg, standardMsg))
1243
Ezio Melottied3a7d22010-12-01 02:32:32 +00001244 def assertRaisesRegex(self, expected_exception, expected_regex,
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001245 *args, **kwargs):
Ezio Melottied3a7d22010-12-01 02:32:32 +00001246 """Asserts that the message in a raised exception matches a regex.
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001247
1248 Args:
1249 expected_exception: Exception class expected to be raised.
Ezio Melottied3a7d22010-12-01 02:32:32 +00001250 expected_regex: Regex (re pattern object or string) expected
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001251 to be found in error message.
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001252 args: Function to be called and extra positional args.
1253 kwargs: Extra kwargs.
Ezio Melottib4dc2502011-05-06 15:01:41 +03001254 msg: Optional message used in case of failure. Can only be used
1255 when assertRaisesRegex is used as a context manager.
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001256 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001257 context = _AssertRaisesContext(expected_exception, self, expected_regex)
1258 return context.handle('assertRaisesRegex', args, kwargs)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001259
Ezio Melottied3a7d22010-12-01 02:32:32 +00001260 def assertWarnsRegex(self, expected_warning, expected_regex,
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001261 *args, **kwargs):
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001262 """Asserts that the message in a triggered warning matches a regexp.
1263 Basic functioning is similar to assertWarns() with the addition
1264 that only warnings whose messages also match the regular expression
1265 are considered successful matches.
1266
1267 Args:
1268 expected_warning: Warning class expected to be triggered.
Ezio Melottied3a7d22010-12-01 02:32:32 +00001269 expected_regex: Regex (re pattern object or string) expected
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001270 to be found in error message.
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001271 args: Function to be called and extra positional args.
1272 kwargs: Extra kwargs.
Ezio Melottib4dc2502011-05-06 15:01:41 +03001273 msg: Optional message used in case of failure. Can only be used
1274 when assertWarnsRegex is used as a context manager.
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001275 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001276 context = _AssertWarnsContext(expected_warning, self, expected_regex)
1277 return context.handle('assertWarnsRegex', args, kwargs)
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001278
Ezio Melottied3a7d22010-12-01 02:32:32 +00001279 def assertRegex(self, text, expected_regex, msg=None):
Michael Foorde3ef5f12010-05-08 16:46:14 +00001280 """Fail the test unless the text matches the regular expression."""
Ezio Melottied3a7d22010-12-01 02:32:32 +00001281 if isinstance(expected_regex, (str, bytes)):
Gregory P. Smithed16bf42010-12-16 19:23:05 +00001282 assert expected_regex, "expected_regex must not be empty."
Ezio Melottied3a7d22010-12-01 02:32:32 +00001283 expected_regex = re.compile(expected_regex)
1284 if not expected_regex.search(text):
Robert Collinsbe6caca2015-08-20 11:13:09 +12001285 standardMsg = "Regex didn't match: %r not found in %r" % (
1286 expected_regex.pattern, text)
1287 # _formatMessage ensures the longMessage option is respected
1288 msg = self._formatMessage(msg, standardMsg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001289 raise self.failureException(msg)
1290
Ezio Melotti8f776302010-12-10 02:32:05 +00001291 def assertNotRegex(self, text, unexpected_regex, msg=None):
Michael Foorde3ef5f12010-05-08 16:46:14 +00001292 """Fail the test if the text matches the regular expression."""
Ezio Melottied3a7d22010-12-01 02:32:32 +00001293 if isinstance(unexpected_regex, (str, bytes)):
1294 unexpected_regex = re.compile(unexpected_regex)
1295 match = unexpected_regex.search(text)
Benjamin Petersonb48af542010-04-11 20:43:16 +00001296 if match:
Robert Collinsbe6caca2015-08-20 11:13:09 +12001297 standardMsg = 'Regex matched: %r matches %r in %r' % (
1298 text[match.start() : match.end()],
1299 unexpected_regex.pattern,
1300 text)
1301 # _formatMessage ensures the longMessage option is respected
1302 msg = self._formatMessage(msg, standardMsg)
Benjamin Petersonb48af542010-04-11 20:43:16 +00001303 raise self.failureException(msg)
1304
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001305
Ezio Melottied3a7d22010-12-01 02:32:32 +00001306 def _deprecate(original_func):
1307 def deprecated_func(*args, **kwargs):
1308 warnings.warn(
1309 'Please use {0} instead.'.format(original_func.__name__),
1310 DeprecationWarning, 2)
1311 return original_func(*args, **kwargs)
1312 return deprecated_func
1313
Ezio Melotti361467e2011-04-03 17:37:58 +03001314 # see #9424
Ezio Melotti0f535012011-04-03 18:02:13 +03001315 failUnlessEqual = assertEquals = _deprecate(assertEqual)
1316 failIfEqual = assertNotEquals = _deprecate(assertNotEqual)
1317 failUnlessAlmostEqual = assertAlmostEquals = _deprecate(assertAlmostEqual)
1318 failIfAlmostEqual = assertNotAlmostEquals = _deprecate(assertNotAlmostEqual)
1319 failUnless = assert_ = _deprecate(assertTrue)
1320 failUnlessRaises = _deprecate(assertRaises)
1321 failIf = _deprecate(assertFalse)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001322 assertRaisesRegexp = _deprecate(assertRaisesRegex)
1323 assertRegexpMatches = _deprecate(assertRegex)
Robert Collinsbe6caca2015-08-20 11:13:09 +12001324 assertNotRegexpMatches = _deprecate(assertNotRegex)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001325
1326
1327
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001328class FunctionTestCase(TestCase):
1329 """A test case that wraps a test function.
1330
1331 This is useful for slipping pre-existing test functions into the
1332 unittest framework. Optionally, set-up and tidy-up functions can be
1333 supplied. As with TestCase, the tidy-up ('tearDown') function will
1334 always be called if the set-up ('setUp') function ran successfully.
1335 """
1336
1337 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
1338 super(FunctionTestCase, self).__init__()
1339 self._setUpFunc = setUp
1340 self._tearDownFunc = tearDown
1341 self._testFunc = testFunc
1342 self._description = description
1343
1344 def setUp(self):
1345 if self._setUpFunc is not None:
1346 self._setUpFunc()
1347
1348 def tearDown(self):
1349 if self._tearDownFunc is not None:
1350 self._tearDownFunc()
1351
1352 def runTest(self):
1353 self._testFunc()
1354
1355 def id(self):
1356 return self._testFunc.__name__
1357
1358 def __eq__(self, other):
1359 if not isinstance(other, self.__class__):
1360 return NotImplemented
1361
1362 return self._setUpFunc == other._setUpFunc and \
1363 self._tearDownFunc == other._tearDownFunc and \
1364 self._testFunc == other._testFunc and \
1365 self._description == other._description
1366
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001367 def __hash__(self):
1368 return hash((type(self), self._setUpFunc, self._tearDownFunc,
1369 self._testFunc, self._description))
1370
1371 def __str__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001372 return "%s (%s)" % (strclass(self.__class__),
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001373 self._testFunc.__name__)
1374
1375 def __repr__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001376 return "<%s tec=%s>" % (strclass(self.__class__),
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001377 self._testFunc)
1378
1379 def shortDescription(self):
1380 if self._description is not None:
1381 return self._description
1382 doc = self._testFunc.__doc__
1383 return doc and doc.split("\n")[0].strip() or None
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +01001384
1385
1386class _SubTest(TestCase):
1387
1388 def __init__(self, test_case, message, params):
1389 super().__init__()
1390 self._message = message
1391 self.test_case = test_case
1392 self.params = params
1393 self.failureException = test_case.failureException
1394
1395 def runTest(self):
1396 raise NotImplementedError("subtests cannot be run directly")
1397
1398 def _subDescription(self):
1399 parts = []
1400 if self._message:
1401 parts.append("[{}]".format(self._message))
1402 if self.params:
1403 params_desc = ', '.join(
1404 "{}={!r}".format(k, v)
1405 for (k, v) in sorted(self.params.items()))
1406 parts.append("({})".format(params_desc))
1407 return " ".join(parts) or '(<subtest>)'
1408
1409 def id(self):
1410 return "{} {}".format(self.test_case.id(), self._subDescription())
1411
1412 def shortDescription(self):
1413 """Returns a one-line description of the subtest, or None if no
1414 description has been provided.
1415 """
1416 return self.test_case.shortDescription()
1417
1418 def __str__(self):
1419 return "{} {}".format(self.test_case, self._subDescription())