blob: b523f73ff2278436b1cdcfe8a494a6e105687148 [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
Berker Peksag16ea19f2016-09-21 19:34:15 +030020_subtest_msg_sentinel = object()
Michael Foord9dad32e2010-06-05 13:49:56 +000021
22DIFF_OMITTED = ('\nDiff is %s characters long. '
23 'Set self.maxDiff to None to see it.')
24
Benjamin Petersonbed7d042009-07-19 21:01:52 +000025class SkipTest(Exception):
26 """
27 Raise this exception in a test to skip it.
28
Ezio Melotti265281a2013-03-27 20:11:55 +020029 Usually you can use TestCase.skipTest() or one of the skipping decorators
Benjamin Petersonbed7d042009-07-19 21:01:52 +000030 instead of raising this directly.
31 """
Benjamin Petersonbed7d042009-07-19 21:01:52 +000032
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010033class _ShouldStop(Exception):
Benjamin Petersonbed7d042009-07-19 21:01:52 +000034 """
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010035 The test should stop.
Benjamin Petersonbed7d042009-07-19 21:01:52 +000036 """
37
Benjamin Petersonbed7d042009-07-19 21:01:52 +000038class _UnexpectedSuccess(Exception):
39 """
40 The test was supposed to fail, but it didn't!
41 """
Michael Foordb3468f72010-12-19 03:19:47 +000042
43
44class _Outcome(object):
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010045 def __init__(self, result=None):
46 self.expecting_failure = False
47 self.result = result
48 self.result_supports_subtests = hasattr(result, "addSubTest")
Michael Foordb3468f72010-12-19 03:19:47 +000049 self.success = True
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010050 self.skipped = []
Michael Foordb3468f72010-12-19 03:19:47 +000051 self.expectedFailure = None
52 self.errors = []
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010053
54 @contextlib.contextmanager
55 def testPartExecutor(self, test_case, isTest=False):
56 old_success = self.success
57 self.success = True
58 try:
59 yield
60 except KeyboardInterrupt:
61 raise
62 except SkipTest as e:
63 self.success = False
64 self.skipped.append((test_case, str(e)))
65 except _ShouldStop:
66 pass
67 except:
68 exc_info = sys.exc_info()
69 if self.expecting_failure:
70 self.expectedFailure = exc_info
71 else:
72 self.success = False
73 self.errors.append((test_case, exc_info))
Victor Stinner031bd532013-12-09 01:52:50 +010074 # explicitly break a reference cycle:
75 # exc_info -> frame -> exc_info
76 exc_info = None
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +010077 else:
78 if self.result_supports_subtests and self.success:
79 self.errors.append((test_case, None))
80 finally:
81 self.success = self.success and old_success
Michael Foordb3468f72010-12-19 03:19:47 +000082
Benjamin Petersonbed7d042009-07-19 21:01:52 +000083
84def _id(obj):
85 return obj
86
87def skip(reason):
88 """
89 Unconditionally skip a test.
90 """
91 def decorator(test_item):
Antoine Pitroub05ac862012-04-25 14:56:46 +020092 if not isinstance(test_item, type):
Benjamin Peterson847a4112010-03-14 15:04:17 +000093 @functools.wraps(test_item)
94 def skip_wrapper(*args, **kwargs):
95 raise SkipTest(reason)
96 test_item = skip_wrapper
97
98 test_item.__unittest_skip__ = True
99 test_item.__unittest_skip_why__ = reason
100 return test_item
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000101 return decorator
102
103def skipIf(condition, reason):
104 """
105 Skip a test if the condition is true.
106 """
107 if condition:
108 return skip(reason)
109 return _id
110
111def skipUnless(condition, reason):
112 """
113 Skip a test unless the condition is true.
114 """
115 if not condition:
116 return skip(reason)
117 return _id
118
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100119def expectedFailure(test_item):
120 test_item.__unittest_expecting_failure__ = True
121 return test_item
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000122
Serhiy Storchaka041dd8e2015-05-21 20:15:40 +0300123def _is_subtype(expected, basetype):
124 if isinstance(expected, tuple):
125 return all(_is_subtype(e, basetype) for e in expected)
126 return isinstance(expected, type) and issubclass(expected, basetype)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000127
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200128class _BaseTestCaseContext:
129
130 def __init__(self, test_case):
131 self.test_case = test_case
132
133 def _raiseFailure(self, standardMsg):
134 msg = self.test_case._formatMessage(self.msg, standardMsg)
135 raise self.test_case.failureException(msg)
136
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200137class _AssertRaisesBaseContext(_BaseTestCaseContext):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000138
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300139 def __init__(self, expected, test_case, expected_regex=None):
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200140 _BaseTestCaseContext.__init__(self, test_case)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000141 self.expected = expected
Ezio Melottib4dc2502011-05-06 15:01:41 +0300142 self.test_case = test_case
R David Murrayef1c2672014-03-25 15:31:50 -0400143 if expected_regex is not None:
Ezio Melottied3a7d22010-12-01 02:32:32 +0000144 expected_regex = re.compile(expected_regex)
145 self.expected_regex = expected_regex
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300146 self.obj_name = None
Ezio Melottib4dc2502011-05-06 15:01:41 +0300147 self.msg = None
148
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300149 def handle(self, name, args, kwargs):
Ezio Melottib4dc2502011-05-06 15:01:41 +0300150 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300151 If args is empty, assertRaises/Warns is being used as a
Ezio Melottib4dc2502011-05-06 15:01:41 +0300152 context manager, so check for a 'msg' kwarg and return self.
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300153 If args is not empty, call a callable passing positional and keyword
154 arguments.
Ezio Melottib4dc2502011-05-06 15:01:41 +0300155 """
Serhiy Storchaka041dd8e2015-05-21 20:15:40 +0300156 if not _is_subtype(self.expected, self._base_type):
157 raise TypeError('%s() arg 1 must be %s' %
158 (name, self._base_type_str))
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300159 if args and args[0] is None:
160 warnings.warn("callable is None",
161 DeprecationWarning, 3)
162 args = ()
163 if not args:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300164 self.msg = kwargs.pop('msg', None)
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300165 if kwargs:
166 warnings.warn('%r is an invalid keyword argument for '
167 'this function' % next(iter(kwargs)),
168 DeprecationWarning, 3)
Ezio Melottib4dc2502011-05-06 15:01:41 +0300169 return self
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300170
171 callable_obj, *args = args
172 try:
173 self.obj_name = callable_obj.__name__
174 except AttributeError:
175 self.obj_name = str(callable_obj)
Ezio Melottib4dc2502011-05-06 15:01:41 +0300176 with self:
177 callable_obj(*args, **kwargs)
178
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000179
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000180class _AssertRaisesContext(_AssertRaisesBaseContext):
181 """A context manager used to implement TestCase.assertRaises* methods."""
182
Serhiy Storchaka041dd8e2015-05-21 20:15:40 +0300183 _base_type = BaseException
184 _base_type_str = 'an exception type or tuple of exception types'
185
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000186 def __enter__(self):
Ezio Melotti49008232010-02-08 21:57:48 +0000187 return self
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000188
189 def __exit__(self, exc_type, exc_value, tb):
190 if exc_type is None:
191 try:
192 exc_name = self.expected.__name__
193 except AttributeError:
194 exc_name = str(self.expected)
195 if self.obj_name:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300196 self._raiseFailure("{} not raised by {}".format(exc_name,
197 self.obj_name))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000198 else:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300199 self._raiseFailure("{} not raised".format(exc_name))
Antoine Pitrou96810222014-04-29 01:23:50 +0200200 else:
201 traceback.clear_frames(tb)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000202 if not issubclass(exc_type, self.expected):
203 # let unexpected exceptions pass through
204 return False
Ezio Melotti49008232010-02-08 21:57:48 +0000205 # store exception, without traceback, for later retrieval
206 self.exception = exc_value.with_traceback(None)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000207 if self.expected_regex is None:
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000208 return True
209
Ezio Melottied3a7d22010-12-01 02:32:32 +0000210 expected_regex = self.expected_regex
211 if not expected_regex.search(str(exc_value)):
Ezio Melottib4dc2502011-05-06 15:01:41 +0300212 self._raiseFailure('"{}" does not match "{}"'.format(
213 expected_regex.pattern, str(exc_value)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000214 return True
215
216
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000217class _AssertWarnsContext(_AssertRaisesBaseContext):
218 """A context manager used to implement TestCase.assertWarns* methods."""
219
Serhiy Storchaka041dd8e2015-05-21 20:15:40 +0300220 _base_type = Warning
221 _base_type_str = 'a warning type or tuple of warning types'
222
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000223 def __enter__(self):
224 # The __warningregistry__'s need to be in a pristine state for tests
225 # to work properly.
226 for v in sys.modules.values():
227 if getattr(v, '__warningregistry__', None):
228 v.__warningregistry__ = {}
229 self.warnings_manager = warnings.catch_warnings(record=True)
230 self.warnings = self.warnings_manager.__enter__()
231 warnings.simplefilter("always", self.expected)
232 return self
233
234 def __exit__(self, exc_type, exc_value, tb):
235 self.warnings_manager.__exit__(exc_type, exc_value, tb)
236 if exc_type is not None:
237 # let unexpected exceptions pass through
238 return
239 try:
240 exc_name = self.expected.__name__
241 except AttributeError:
242 exc_name = str(self.expected)
243 first_matching = None
244 for m in self.warnings:
245 w = m.message
246 if not isinstance(w, self.expected):
247 continue
248 if first_matching is None:
249 first_matching = w
Ezio Melottied3a7d22010-12-01 02:32:32 +0000250 if (self.expected_regex is not None and
251 not self.expected_regex.search(str(w))):
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000252 continue
253 # store warning for later retrieval
254 self.warning = w
255 self.filename = m.filename
256 self.lineno = m.lineno
257 return
258 # Now we simply try to choose a helpful failure message
259 if first_matching is not None:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300260 self._raiseFailure('"{}" does not match "{}"'.format(
261 self.expected_regex.pattern, str(first_matching)))
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000262 if self.obj_name:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300263 self._raiseFailure("{} not triggered by {}".format(exc_name,
264 self.obj_name))
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000265 else:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300266 self._raiseFailure("{} not triggered".format(exc_name))
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000267
268
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200269
270_LoggingWatcher = collections.namedtuple("_LoggingWatcher",
271 ["records", "output"])
272
273
274class _CapturingHandler(logging.Handler):
275 """
276 A logging handler capturing all (raw and formatted) logging output.
277 """
278
279 def __init__(self):
280 logging.Handler.__init__(self)
281 self.watcher = _LoggingWatcher([], [])
282
283 def flush(self):
284 pass
285
286 def emit(self, record):
287 self.watcher.records.append(record)
288 msg = self.format(record)
289 self.watcher.output.append(msg)
290
291
292
293class _AssertLogsContext(_BaseTestCaseContext):
294 """A context manager used to implement TestCase.assertLogs()."""
295
296 LOGGING_FORMAT = "%(levelname)s:%(name)s:%(message)s"
297
298 def __init__(self, test_case, logger_name, level):
299 _BaseTestCaseContext.__init__(self, test_case)
300 self.logger_name = logger_name
301 if level:
302 self.level = logging._nameToLevel.get(level, level)
303 else:
304 self.level = logging.INFO
305 self.msg = None
306
307 def __enter__(self):
308 if isinstance(self.logger_name, logging.Logger):
309 logger = self.logger = self.logger_name
310 else:
311 logger = self.logger = logging.getLogger(self.logger_name)
312 formatter = logging.Formatter(self.LOGGING_FORMAT)
313 handler = _CapturingHandler()
314 handler.setFormatter(formatter)
315 self.watcher = handler.watcher
316 self.old_handlers = logger.handlers[:]
317 self.old_level = logger.level
318 self.old_propagate = logger.propagate
319 logger.handlers = [handler]
320 logger.setLevel(self.level)
321 logger.propagate = False
322 return handler.watcher
323
324 def __exit__(self, exc_type, exc_value, tb):
325 self.logger.handlers = self.old_handlers
326 self.logger.propagate = self.old_propagate
327 self.logger.setLevel(self.old_level)
328 if exc_type is not None:
329 # let unexpected exceptions pass through
330 return False
331 if len(self.watcher.records) == 0:
332 self._raiseFailure(
333 "no logs of level {} or higher triggered on {}"
334 .format(logging.getLevelName(self.level), self.logger.name))
335
336
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000337class TestCase(object):
338 """A class whose instances are single test cases.
339
340 By default, the test code itself should be placed in a method named
341 'runTest'.
342
343 If the fixture may be used for many test cases, create as
344 many test methods as are needed. When instantiating such a TestCase
345 subclass, specify in the constructor arguments the name of the test method
346 that the instance is to execute.
347
348 Test authors should subclass TestCase for their own tests. Construction
349 and deconstruction of the test's environment ('fixture') can be
350 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
351
352 If it is necessary to override the __init__ method, the base class
353 __init__ method must always be called. It is important that subclasses
354 should not change the signature of their __init__ method, since instances
355 of the classes are instantiated automatically by parts of the framework
356 in order to be run.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000357
Ezio Melotti31797e52013-03-29 03:42:29 +0200358 When subclassing TestCase, you can set these attributes:
359 * failureException: determines which exception will be raised when
360 the instance's assertion methods fail; test methods raising this
361 exception will be deemed to have 'failed' rather than 'errored'.
362 * longMessage: determines whether long messages (including repr of
363 objects used in assert methods) will be printed on failure in *addition*
364 to any explicit message passed.
365 * maxDiff: sets the maximum length of a diff in failure messages
366 by assert methods using difflib. It is looked up as an instance
367 attribute so can be configured by individual tests if required.
368 """
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000369
370 failureException = AssertionError
371
Michael Foord5074df62010-12-03 00:53:09 +0000372 longMessage = True
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000373
Michael Foord085dfd32010-06-05 12:17:02 +0000374 maxDiff = 80*8
375
Ezio Melottiedd117f2011-04-27 10:20:38 +0300376 # If a string is longer than _diffThreshold, use normal comparison instead
377 # of difflib. See #11763.
378 _diffThreshold = 2**16
379
Benjamin Peterson847a4112010-03-14 15:04:17 +0000380 # Attribute used by TestSuite for classSetUp
381
382 _classSetupFailed = False
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000383
384 def __init__(self, methodName='runTest'):
385 """Create an instance of the class that will use the named test
386 method when executed. Raises a ValueError if the instance does
387 not have a method with the specified name.
388 """
389 self._testMethodName = methodName
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100390 self._outcome = None
Michael Foord32e1d832011-01-03 17:00:11 +0000391 self._testMethodDoc = 'No test'
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000392 try:
393 testMethod = getattr(self, methodName)
394 except AttributeError:
Michael Foord32e1d832011-01-03 17:00:11 +0000395 if methodName != 'runTest':
396 # we allow instantiation with no explicit method name
397 # but not an *incorrect* or missing method name
398 raise ValueError("no such test method in %s: %s" %
399 (self.__class__, methodName))
400 else:
401 self._testMethodDoc = testMethod.__doc__
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000402 self._cleanups = []
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100403 self._subtest = None
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000404
405 # Map types to custom assertEqual functions that will compare
406 # instances of said type in more detail to generate a more useful
407 # error message.
Benjamin Peterson34b2b262011-07-12 19:21:42 -0500408 self._type_equality_funcs = {}
Michael Foord8ca6d982010-11-20 15:34:26 +0000409 self.addTypeEqualityFunc(dict, 'assertDictEqual')
410 self.addTypeEqualityFunc(list, 'assertListEqual')
411 self.addTypeEqualityFunc(tuple, 'assertTupleEqual')
412 self.addTypeEqualityFunc(set, 'assertSetEqual')
413 self.addTypeEqualityFunc(frozenset, 'assertSetEqual')
414 self.addTypeEqualityFunc(str, 'assertMultiLineEqual')
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000415
416 def addTypeEqualityFunc(self, typeobj, function):
417 """Add a type specific assertEqual style function to compare a type.
418
419 This method is for use by TestCase subclasses that need to register
420 their own type equality functions to provide nicer error messages.
421
422 Args:
423 typeobj: The data type to call this function on when both values
424 are of the same type in assertEqual().
425 function: The callable taking two arguments and an optional
426 msg= argument that raises self.failureException with a
427 useful error message when the two arguments are not equal.
428 """
Benjamin Peterson8f326b22009-12-13 02:10:36 +0000429 self._type_equality_funcs[typeobj] = function
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000430
431 def addCleanup(self, function, *args, **kwargs):
432 """Add a function, with arguments, to be called when the test is
433 completed. Functions added are called on a LIFO basis and are
434 called after tearDown on test failure or success.
435
436 Cleanup items are called even if setUp fails (unlike tearDown)."""
437 self._cleanups.append((function, args, kwargs))
438
439 def setUp(self):
440 "Hook method for setting up the test fixture before exercising it."
441 pass
442
443 def tearDown(self):
444 "Hook method for deconstructing the test fixture after testing it."
445 pass
446
Benjamin Peterson847a4112010-03-14 15:04:17 +0000447 @classmethod
448 def setUpClass(cls):
449 "Hook method for setting up class fixture before running tests in the class."
450
451 @classmethod
452 def tearDownClass(cls):
453 "Hook method for deconstructing the class fixture after running all tests in the class."
454
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000455 def countTestCases(self):
456 return 1
457
458 def defaultTestResult(self):
459 return result.TestResult()
460
461 def shortDescription(self):
Michael Foord34c94622010-02-10 15:51:42 +0000462 """Returns a one-line description of the test, or None if no
463 description has been provided.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000464
Michael Foord34c94622010-02-10 15:51:42 +0000465 The default implementation of this method returns the first line of
466 the specified test method's docstring.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000467 """
Michael Foord34c94622010-02-10 15:51:42 +0000468 doc = self._testMethodDoc
469 return doc and doc.split("\n")[0].strip() or None
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000470
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000471
472 def id(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000473 return "%s.%s" % (strclass(self.__class__), self._testMethodName)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000474
475 def __eq__(self, other):
476 if type(self) is not type(other):
477 return NotImplemented
478
479 return self._testMethodName == other._testMethodName
480
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000481 def __hash__(self):
482 return hash((type(self), self._testMethodName))
483
484 def __str__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000485 return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000486
487 def __repr__(self):
488 return "<%s testMethod=%s>" % \
Benjamin Peterson847a4112010-03-14 15:04:17 +0000489 (strclass(self.__class__), self._testMethodName)
490
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100491 def _addSkip(self, result, test_case, reason):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000492 addSkip = getattr(result, 'addSkip', None)
493 if addSkip is not None:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100494 addSkip(test_case, reason)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000495 else:
496 warnings.warn("TestResult has no addSkip method, skips not reported",
497 RuntimeWarning, 2)
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100498 result.addSuccess(test_case)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000499
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100500 @contextlib.contextmanager
Berker Peksag16ea19f2016-09-21 19:34:15 +0300501 def subTest(self, msg=_subtest_msg_sentinel, **params):
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100502 """Return a context manager that will return the enclosed block
503 of code in a subtest identified by the optional message and
504 keyword parameters. A failure in the subtest marks the test
505 case as failed but resumes execution at the end of the enclosed
506 block, allowing further test code to be executed.
507 """
508 if not self._outcome.result_supports_subtests:
509 yield
510 return
511 parent = self._subtest
512 if parent is None:
513 params_map = collections.ChainMap(params)
514 else:
515 params_map = parent.params.new_child(params)
516 self._subtest = _SubTest(self, msg, params_map)
Michael Foordb3468f72010-12-19 03:19:47 +0000517 try:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100518 with self._outcome.testPartExecutor(self._subtest, isTest=True):
519 yield
520 if not self._outcome.success:
521 result = self._outcome.result
522 if result is not None and result.failfast:
523 raise _ShouldStop
524 elif self._outcome.expectedFailure:
525 # If the test is expecting a failure, we really want to
526 # stop now and register the expected failure.
527 raise _ShouldStop
528 finally:
529 self._subtest = parent
530
531 def _feedErrorsToResult(self, result, errors):
532 for test, exc_info in errors:
533 if isinstance(test, _SubTest):
534 result.addSubTest(test.test_case, test, exc_info)
535 elif exc_info is not None:
536 if issubclass(exc_info[0], self.failureException):
537 result.addFailure(test, exc_info)
538 else:
539 result.addError(test, exc_info)
540
541 def _addExpectedFailure(self, result, exc_info):
542 try:
543 addExpectedFailure = result.addExpectedFailure
544 except AttributeError:
545 warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
546 RuntimeWarning)
547 result.addSuccess(self)
548 else:
549 addExpectedFailure(self, exc_info)
550
551 def _addUnexpectedSuccess(self, result):
552 try:
553 addUnexpectedSuccess = result.addUnexpectedSuccess
554 except AttributeError:
555 warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failure",
556 RuntimeWarning)
557 # We need to pass an actual exception and traceback to addFailure,
558 # otherwise the legacy result can choke.
559 try:
560 raise _UnexpectedSuccess from None
561 except _UnexpectedSuccess:
562 result.addFailure(self, sys.exc_info())
563 else:
564 addUnexpectedSuccess(self)
Michael Foordb3468f72010-12-19 03:19:47 +0000565
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000566 def run(self, result=None):
567 orig_result = result
568 if result is None:
569 result = self.defaultTestResult()
570 startTestRun = getattr(result, 'startTestRun', None)
571 if startTestRun is not None:
572 startTestRun()
573
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000574 result.startTest(self)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000575
576 testMethod = getattr(self, self._testMethodName)
577 if (getattr(self.__class__, "__unittest_skip__", False) or
578 getattr(testMethod, "__unittest_skip__", False)):
579 # If the class or method was skipped.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000580 try:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000581 skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
582 or getattr(testMethod, '__unittest_skip_why__', ''))
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100583 self._addSkip(result, self, skip_why)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000584 finally:
585 result.stopTest(self)
586 return
Robert Collinsed599b72015-08-28 10:34:51 +1200587 expecting_failure_method = getattr(testMethod,
588 "__unittest_expecting_failure__", False)
589 expecting_failure_class = getattr(self,
590 "__unittest_expecting_failure__", False)
591 expecting_failure = expecting_failure_class or expecting_failure_method
Victor Stinner031bd532013-12-09 01:52:50 +0100592 outcome = _Outcome(result)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000593 try:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100594 self._outcome = outcome
Michael Foordb3468f72010-12-19 03:19:47 +0000595
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100596 with outcome.testPartExecutor(self):
597 self.setUp()
Michael Foordb3468f72010-12-19 03:19:47 +0000598 if outcome.success:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100599 outcome.expecting_failure = expecting_failure
600 with outcome.testPartExecutor(self, isTest=True):
601 testMethod()
602 outcome.expecting_failure = False
603 with outcome.testPartExecutor(self):
604 self.tearDown()
Michael Foordb3468f72010-12-19 03:19:47 +0000605
606 self.doCleanups()
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100607 for test, reason in outcome.skipped:
608 self._addSkip(result, test, reason)
609 self._feedErrorsToResult(result, outcome.errors)
Michael Foordb3468f72010-12-19 03:19:47 +0000610 if outcome.success:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100611 if expecting_failure:
612 if outcome.expectedFailure:
613 self._addExpectedFailure(result, outcome.expectedFailure)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000614 else:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100615 self._addUnexpectedSuccess(result)
616 else:
617 result.addSuccess(self)
Michael Foord1341bb02011-03-14 19:01:46 -0400618 return result
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000619 finally:
620 result.stopTest(self)
621 if orig_result is None:
622 stopTestRun = getattr(result, 'stopTestRun', None)
623 if stopTestRun is not None:
624 stopTestRun()
625
Victor Stinner031bd532013-12-09 01:52:50 +0100626 # explicitly break reference cycles:
627 # outcome.errors -> frame -> outcome -> outcome.errors
628 # outcome.expectedFailure -> frame -> outcome -> outcome.expectedFailure
629 outcome.errors.clear()
630 outcome.expectedFailure = None
631
632 # clear the outcome, no more needed
633 self._outcome = None
634
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000635 def doCleanups(self):
636 """Execute all cleanup functions. Normally called for you after
637 tearDown."""
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100638 outcome = self._outcome or _Outcome()
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000639 while self._cleanups:
Michael Foordb3468f72010-12-19 03:19:47 +0000640 function, args, kwargs = self._cleanups.pop()
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100641 with outcome.testPartExecutor(self):
642 function(*args, **kwargs)
Michael Foordb3468f72010-12-19 03:19:47 +0000643
644 # return this for backwards compatibility
645 # even though we no longer us it internally
646 return outcome.success
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000647
648 def __call__(self, *args, **kwds):
649 return self.run(*args, **kwds)
650
651 def debug(self):
652 """Run the test without collecting errors in a TestResult"""
653 self.setUp()
654 getattr(self, self._testMethodName)()
655 self.tearDown()
Michael Foordb8748742010-06-10 16:16:08 +0000656 while self._cleanups:
657 function, args, kwargs = self._cleanups.pop(-1)
658 function(*args, **kwargs)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000659
660 def skipTest(self, reason):
661 """Skip this test."""
662 raise SkipTest(reason)
663
664 def fail(self, msg=None):
665 """Fail immediately, with the given message."""
666 raise self.failureException(msg)
667
668 def assertFalse(self, expr, msg=None):
Ezio Melotti3044fa72010-12-18 17:31:58 +0000669 """Check that the expression is false."""
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000670 if expr:
Ezio Melotti3044fa72010-12-18 17:31:58 +0000671 msg = self._formatMessage(msg, "%s is not false" % safe_repr(expr))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000672 raise self.failureException(msg)
673
674 def assertTrue(self, expr, msg=None):
Ezio Melotti3044fa72010-12-18 17:31:58 +0000675 """Check that the expression is true."""
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000676 if not expr:
Ezio Melotti3044fa72010-12-18 17:31:58 +0000677 msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000678 raise self.failureException(msg)
679
680 def _formatMessage(self, msg, standardMsg):
681 """Honour the longMessage attribute when generating failure messages.
682 If longMessage is False this means:
683 * Use only an explicit message if it is provided
684 * Otherwise use the standard message for the assert
685
686 If longMessage is True:
687 * Use the standard message
688 * If an explicit message is provided, plus ' : ' and the explicit message
689 """
690 if not self.longMessage:
691 return msg or standardMsg
692 if msg is None:
693 return standardMsg
Benjamin Peterson847a4112010-03-14 15:04:17 +0000694 try:
695 # don't switch to '{}' formatting in Python 2.X
696 # it changes the way unicode input is handled
697 return '%s : %s' % (standardMsg, msg)
698 except UnicodeDecodeError:
699 return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000700
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300701 def assertRaises(self, expected_exception, *args, **kwargs):
702 """Fail unless an exception of class expected_exception is raised
703 by the callable when invoked with specified positional and
704 keyword arguments. If a different type of exception is
Andrew Svetlov737fb892012-12-18 21:14:22 +0200705 raised, it will not be caught, and the test case will be
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000706 deemed to have suffered an error, exactly as for an
707 unexpected exception.
708
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300709 If called with the callable and arguments omitted, will return a
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000710 context object used like this::
711
Michael Foord1c42b122010-02-05 22:58:21 +0000712 with self.assertRaises(SomeException):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000713 do_something()
Michael Foord1c42b122010-02-05 22:58:21 +0000714
Ezio Melottib4dc2502011-05-06 15:01:41 +0300715 An optional keyword argument 'msg' can be provided when assertRaises
716 is used as a context object.
717
Michael Foord1c42b122010-02-05 22:58:21 +0000718 The context manager keeps a reference to the exception as
Ezio Melotti49008232010-02-08 21:57:48 +0000719 the 'exception' attribute. This allows you to inspect the
Michael Foord1c42b122010-02-05 22:58:21 +0000720 exception after the assertion::
721
722 with self.assertRaises(SomeException) as cm:
723 do_something()
Ezio Melotti49008232010-02-08 21:57:48 +0000724 the_exception = cm.exception
Michael Foordb57ac6d2010-02-05 23:26:29 +0000725 self.assertEqual(the_exception.error_code, 3)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000726 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300727 context = _AssertRaisesContext(expected_exception, self)
728 return context.handle('assertRaises', args, kwargs)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000729
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300730 def assertWarns(self, expected_warning, *args, **kwargs):
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000731 """Fail unless a warning of class warnClass is triggered
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300732 by the callable when invoked with specified positional and
733 keyword arguments. If a different type of warning is
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000734 triggered, it will not be handled: depending on the other
735 warning filtering rules in effect, it might be silenced, printed
736 out, or raised as an exception.
737
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300738 If called with the callable and arguments omitted, will return a
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000739 context object used like this::
740
741 with self.assertWarns(SomeWarning):
742 do_something()
743
Ezio Melottib4dc2502011-05-06 15:01:41 +0300744 An optional keyword argument 'msg' can be provided when assertWarns
745 is used as a context object.
746
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000747 The context manager keeps a reference to the first matching
748 warning as the 'warning' attribute; similarly, the 'filename'
749 and 'lineno' attributes give you information about the line
750 of Python code from which the warning was triggered.
751 This allows you to inspect the warning after the assertion::
752
753 with self.assertWarns(SomeWarning) as cm:
754 do_something()
755 the_warning = cm.warning
756 self.assertEqual(the_warning.some_attribute, 147)
757 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300758 context = _AssertWarnsContext(expected_warning, self)
759 return context.handle('assertWarns', args, kwargs)
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000760
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200761 def assertLogs(self, logger=None, level=None):
762 """Fail unless a log message of level *level* or higher is emitted
763 on *logger_name* or its children. If omitted, *level* defaults to
764 INFO and *logger* defaults to the root logger.
765
766 This method must be used as a context manager, and will yield
767 a recording object with two attributes: `output` and `records`.
768 At the end of the context manager, the `output` attribute will
769 be a list of the matching formatted log messages and the
770 `records` attribute will be a list of the corresponding LogRecord
771 objects.
772
773 Example::
774
775 with self.assertLogs('foo', level='INFO') as cm:
776 logging.getLogger('foo').info('first message')
777 logging.getLogger('foo.bar').error('second message')
778 self.assertEqual(cm.output, ['INFO:foo:first message',
779 'ERROR:foo.bar:second message'])
780 """
781 return _AssertLogsContext(self, logger, level)
782
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000783 def _getAssertEqualityFunc(self, first, second):
784 """Get a detailed comparison function for the types of the two args.
785
786 Returns: A callable accepting (first, second, msg=None) that will
787 raise a failure exception if first != second with a useful human
788 readable error message for those types.
789 """
790 #
791 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
792 # and vice versa. I opted for the conservative approach in case
793 # subclasses are not intended to be compared in detail to their super
794 # class instances using a type equality func. This means testing
795 # subtypes won't automagically use the detailed comparison. Callers
796 # should use their type specific assertSpamEqual method to compare
797 # subclasses if the detailed comparison is desired and appropriate.
798 # See the discussion in http://bugs.python.org/issue2578.
799 #
800 if type(first) is type(second):
801 asserter = self._type_equality_funcs.get(type(first))
802 if asserter is not None:
Benjamin Peterson34b2b262011-07-12 19:21:42 -0500803 if isinstance(asserter, str):
804 asserter = getattr(self, asserter)
Benjamin Peterson8f326b22009-12-13 02:10:36 +0000805 return asserter
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000806
807 return self._baseAssertEqual
808
809 def _baseAssertEqual(self, first, second, msg=None):
810 """The default assertEqual implementation, not type specific."""
811 if not first == second:
Serhiy Storchaka77622f52013-09-23 23:07:00 +0300812 standardMsg = '%s != %s' % _common_shorten_repr(first, second)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000813 msg = self._formatMessage(msg, standardMsg)
814 raise self.failureException(msg)
815
816 def assertEqual(self, first, second, msg=None):
817 """Fail if the two objects are unequal as determined by the '=='
818 operator.
819 """
820 assertion_func = self._getAssertEqualityFunc(first, second)
821 assertion_func(first, second, msg=msg)
822
823 def assertNotEqual(self, first, second, msg=None):
Ezio Melotti90eea972012-11-08 11:08:39 +0200824 """Fail if the two objects are equal as determined by the '!='
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000825 operator.
826 """
827 if not first != second:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000828 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
829 safe_repr(second)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000830 raise self.failureException(msg)
831
Michael Foord321d0592010-11-02 13:44:51 +0000832 def assertAlmostEqual(self, first, second, places=None, msg=None,
Benjamin Petersonb48af542010-04-11 20:43:16 +0000833 delta=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000834 """Fail if the two objects are unequal as determined by their
835 difference rounded to the given number of decimal places
Benjamin Petersonb48af542010-04-11 20:43:16 +0000836 (default 7) and comparing to zero, or by comparing that the
837 between the two objects is more than the given delta.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000838
839 Note that decimal places (from zero) are usually not the same
Martin Pantereb995702016-07-28 01:11:04 +0000840 as significant digits (measured from the most significant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000841
842 If the two objects compare equal then they will automatically
843 compare almost equal.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000844 """
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000845 if first == second:
Benjamin Petersonb48af542010-04-11 20:43:16 +0000846 # shortcut
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000847 return
Benjamin Petersonb48af542010-04-11 20:43:16 +0000848 if delta is not None and places is not None:
849 raise TypeError("specify delta or places not both")
850
851 if delta is not None:
852 if abs(first - second) <= delta:
853 return
854
855 standardMsg = '%s != %s within %s delta' % (safe_repr(first),
856 safe_repr(second),
857 safe_repr(delta))
858 else:
859 if places is None:
860 places = 7
861
862 if round(abs(second-first), places) == 0:
863 return
864
Benjamin Peterson847a4112010-03-14 15:04:17 +0000865 standardMsg = '%s != %s within %r places' % (safe_repr(first),
866 safe_repr(second),
867 places)
Benjamin Petersonb48af542010-04-11 20:43:16 +0000868 msg = self._formatMessage(msg, standardMsg)
869 raise self.failureException(msg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000870
Michael Foord321d0592010-11-02 13:44:51 +0000871 def assertNotAlmostEqual(self, first, second, places=None, msg=None,
Benjamin Petersonb48af542010-04-11 20:43:16 +0000872 delta=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000873 """Fail if the two objects are equal as determined by their
874 difference rounded to the given number of decimal places
Benjamin Petersonb48af542010-04-11 20:43:16 +0000875 (default 7) and comparing to zero, or by comparing that the
876 between the two objects is less than the given delta.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000877
878 Note that decimal places (from zero) are usually not the same
Martin Pantereb995702016-07-28 01:11:04 +0000879 as significant digits (measured from the most significant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000880
881 Objects that are equal automatically fail.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000882 """
Benjamin Petersonb48af542010-04-11 20:43:16 +0000883 if delta is not None and places is not None:
884 raise TypeError("specify delta or places not both")
885 if delta is not None:
886 if not (first == second) and abs(first - second) > delta:
887 return
888 standardMsg = '%s == %s within %s delta' % (safe_repr(first),
889 safe_repr(second),
890 safe_repr(delta))
891 else:
892 if places is None:
893 places = 7
894 if not (first == second) and round(abs(second-first), places) != 0:
895 return
Benjamin Peterson847a4112010-03-14 15:04:17 +0000896 standardMsg = '%s == %s within %r places' % (safe_repr(first),
Benjamin Petersonb48af542010-04-11 20:43:16 +0000897 safe_repr(second),
898 places)
899
900 msg = self._formatMessage(msg, standardMsg)
901 raise self.failureException(msg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000902
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000903
Michael Foord085dfd32010-06-05 12:17:02 +0000904 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000905 """An equality assertion for ordered sequences (like lists and tuples).
906
R. David Murrayad13f222010-01-29 22:17:58 +0000907 For the purposes of this function, a valid ordered sequence type is one
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000908 which can be indexed, has a length, and has an equality operator.
909
910 Args:
911 seq1: The first sequence to compare.
912 seq2: The second sequence to compare.
913 seq_type: The expected datatype of the sequences, or None if no
914 datatype should be enforced.
915 msg: Optional message to use on failure instead of a list of
916 differences.
917 """
Benjamin Petersonb29614e2012-10-09 11:16:03 -0400918 if seq_type is not None:
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000919 seq_type_name = seq_type.__name__
920 if not isinstance(seq1, seq_type):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000921 raise self.failureException('First sequence is not a %s: %s'
922 % (seq_type_name, safe_repr(seq1)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000923 if not isinstance(seq2, seq_type):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000924 raise self.failureException('Second sequence is not a %s: %s'
925 % (seq_type_name, safe_repr(seq2)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000926 else:
927 seq_type_name = "sequence"
928
929 differing = None
930 try:
931 len1 = len(seq1)
932 except (TypeError, NotImplementedError):
933 differing = 'First %s has no length. Non-sequence?' % (
934 seq_type_name)
935
936 if differing is None:
937 try:
938 len2 = len(seq2)
939 except (TypeError, NotImplementedError):
940 differing = 'Second %s has no length. Non-sequence?' % (
941 seq_type_name)
942
943 if differing is None:
944 if seq1 == seq2:
945 return
946
Serhiy Storchaka77622f52013-09-23 23:07:00 +0300947 differing = '%ss differ: %s != %s\n' % (
948 (seq_type_name.capitalize(),) +
949 _common_shorten_repr(seq1, seq2))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000950
951 for i in range(min(len1, len2)):
952 try:
953 item1 = seq1[i]
954 except (TypeError, IndexError, NotImplementedError):
955 differing += ('\nUnable to index element %d of first %s\n' %
956 (i, seq_type_name))
957 break
958
959 try:
960 item2 = seq2[i]
961 except (TypeError, IndexError, NotImplementedError):
962 differing += ('\nUnable to index element %d of second %s\n' %
963 (i, seq_type_name))
964 break
965
966 if item1 != item2:
967 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
Serhiy Storchaka685fbed2016-04-25 08:58:25 +0300968 ((i,) + _common_shorten_repr(item1, item2)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000969 break
970 else:
971 if (len1 == len2 and seq_type is None and
972 type(seq1) != type(seq2)):
973 # The sequences are the same, but have differing types.
974 return
975
976 if len1 > len2:
977 differing += ('\nFirst %s contains %d additional '
978 'elements.\n' % (seq_type_name, len1 - len2))
979 try:
980 differing += ('First extra element %d:\n%s\n' %
Serhiy Storchaka685fbed2016-04-25 08:58:25 +0300981 (len2, safe_repr(seq1[len2])))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000982 except (TypeError, IndexError, NotImplementedError):
983 differing += ('Unable to index element %d '
984 'of first %s\n' % (len2, seq_type_name))
985 elif len1 < len2:
986 differing += ('\nSecond %s contains %d additional '
987 'elements.\n' % (seq_type_name, len2 - len1))
988 try:
989 differing += ('First extra element %d:\n%s\n' %
Serhiy Storchaka685fbed2016-04-25 08:58:25 +0300990 (len1, safe_repr(seq2[len1])))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000991 except (TypeError, IndexError, NotImplementedError):
992 differing += ('Unable to index element %d '
993 'of second %s\n' % (len1, seq_type_name))
Michael Foord2034d9a2010-06-05 11:27:52 +0000994 standardMsg = differing
995 diffMsg = '\n' + '\n'.join(
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000996 difflib.ndiff(pprint.pformat(seq1).splitlines(),
997 pprint.pformat(seq2).splitlines()))
Michael Foord085dfd32010-06-05 12:17:02 +0000998
999 standardMsg = self._truncateMessage(standardMsg, diffMsg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001000 msg = self._formatMessage(msg, standardMsg)
1001 self.fail(msg)
1002
Michael Foord085dfd32010-06-05 12:17:02 +00001003 def _truncateMessage(self, message, diff):
1004 max_diff = self.maxDiff
1005 if max_diff is None or len(diff) <= max_diff:
1006 return message + diff
Michael Foord9dad32e2010-06-05 13:49:56 +00001007 return message + (DIFF_OMITTED % len(diff))
Michael Foord085dfd32010-06-05 12:17:02 +00001008
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001009 def assertListEqual(self, list1, list2, msg=None):
1010 """A list-specific equality assertion.
1011
1012 Args:
1013 list1: The first list to compare.
1014 list2: The second list to compare.
1015 msg: Optional message to use on failure instead of a list of
1016 differences.
1017
1018 """
1019 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
1020
1021 def assertTupleEqual(self, tuple1, tuple2, msg=None):
1022 """A tuple-specific equality assertion.
1023
1024 Args:
1025 tuple1: The first tuple to compare.
1026 tuple2: The second tuple to compare.
1027 msg: Optional message to use on failure instead of a list of
1028 differences.
1029 """
1030 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
1031
1032 def assertSetEqual(self, set1, set2, msg=None):
1033 """A set-specific equality assertion.
1034
1035 Args:
1036 set1: The first set to compare.
1037 set2: The second set to compare.
1038 msg: Optional message to use on failure instead of a list of
1039 differences.
1040
Michael Foord91c9da32010-03-20 17:21:27 +00001041 assertSetEqual uses ducktyping to support different types of sets, and
1042 is optimized for sets specifically (parameters must support a
1043 difference method).
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001044 """
1045 try:
1046 difference1 = set1.difference(set2)
1047 except TypeError as e:
1048 self.fail('invalid type when attempting set difference: %s' % e)
1049 except AttributeError as e:
1050 self.fail('first argument does not support set difference: %s' % e)
1051
1052 try:
1053 difference2 = set2.difference(set1)
1054 except TypeError as e:
1055 self.fail('invalid type when attempting set difference: %s' % e)
1056 except AttributeError as e:
1057 self.fail('second argument does not support set difference: %s' % e)
1058
1059 if not (difference1 or difference2):
1060 return
1061
1062 lines = []
1063 if difference1:
1064 lines.append('Items in the first set but not the second:')
1065 for item in difference1:
1066 lines.append(repr(item))
1067 if difference2:
1068 lines.append('Items in the second set but not the first:')
1069 for item in difference2:
1070 lines.append(repr(item))
1071
1072 standardMsg = '\n'.join(lines)
1073 self.fail(self._formatMessage(msg, standardMsg))
1074
1075 def assertIn(self, member, container, msg=None):
1076 """Just like self.assertTrue(a in b), but with a nicer default message."""
1077 if member not in container:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001078 standardMsg = '%s not found in %s' % (safe_repr(member),
1079 safe_repr(container))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001080 self.fail(self._formatMessage(msg, standardMsg))
1081
1082 def assertNotIn(self, member, container, msg=None):
1083 """Just like self.assertTrue(a not in b), but with a nicer default message."""
1084 if member in container:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001085 standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
1086 safe_repr(container))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001087 self.fail(self._formatMessage(msg, standardMsg))
1088
1089 def assertIs(self, expr1, expr2, msg=None):
1090 """Just like self.assertTrue(a is b), but with a nicer default message."""
1091 if expr1 is not expr2:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001092 standardMsg = '%s is not %s' % (safe_repr(expr1),
1093 safe_repr(expr2))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001094 self.fail(self._formatMessage(msg, standardMsg))
1095
1096 def assertIsNot(self, expr1, expr2, msg=None):
1097 """Just like self.assertTrue(a is not b), but with a nicer default message."""
1098 if expr1 is expr2:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001099 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001100 self.fail(self._formatMessage(msg, standardMsg))
1101
1102 def assertDictEqual(self, d1, d2, msg=None):
Ezio Melottib3aedd42010-11-20 19:04:17 +00001103 self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
1104 self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001105
1106 if d1 != d2:
Serhiy Storchaka77622f52013-09-23 23:07:00 +03001107 standardMsg = '%s != %s' % _common_shorten_repr(d1, d2)
Michael Foord085dfd32010-06-05 12:17:02 +00001108 diff = ('\n' + '\n'.join(difflib.ndiff(
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001109 pprint.pformat(d1).splitlines(),
1110 pprint.pformat(d2).splitlines())))
Michael Foordcb11b252010-06-05 13:14:43 +00001111 standardMsg = self._truncateMessage(standardMsg, diff)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001112 self.fail(self._formatMessage(msg, standardMsg))
1113
Ezio Melotti0f535012011-04-03 18:02:13 +03001114 def assertDictContainsSubset(self, subset, dictionary, msg=None):
1115 """Checks whether dictionary is a superset of subset."""
1116 warnings.warn('assertDictContainsSubset is deprecated',
1117 DeprecationWarning)
1118 missing = []
1119 mismatched = []
1120 for key, value in subset.items():
1121 if key not in dictionary:
1122 missing.append(key)
1123 elif value != dictionary[key]:
1124 mismatched.append('%s, expected: %s, actual: %s' %
1125 (safe_repr(key), safe_repr(value),
1126 safe_repr(dictionary[key])))
1127
1128 if not (missing or mismatched):
1129 return
1130
1131 standardMsg = ''
1132 if missing:
1133 standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
1134 missing)
1135 if mismatched:
1136 if standardMsg:
1137 standardMsg += '; '
1138 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
1139
1140 self.fail(self._formatMessage(msg, standardMsg))
1141
1142
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001143 def assertCountEqual(self, first, second, msg=None):
1144 """An unordered sequence comparison asserting that the same elements,
1145 regardless of order. If the same element occurs more than once,
1146 it verifies that the elements occur the same number of times.
Michael Foord8442a602010-03-20 16:58:04 +00001147
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001148 self.assertEqual(Counter(list(first)),
1149 Counter(list(second)))
Michael Foord8442a602010-03-20 16:58:04 +00001150
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001151 Example:
Michael Foord8442a602010-03-20 16:58:04 +00001152 - [0, 1, 1] and [1, 0, 1] compare equal.
1153 - [0, 0, 1] and [0, 1] compare unequal.
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001154
Michael Foord8442a602010-03-20 16:58:04 +00001155 """
Michael Foorde180d392011-01-28 19:51:48 +00001156 first_seq, second_seq = list(first), list(second)
Michael Foord8442a602010-03-20 16:58:04 +00001157 try:
Michael Foorde180d392011-01-28 19:51:48 +00001158 first = collections.Counter(first_seq)
1159 second = collections.Counter(second_seq)
Michael Foord8442a602010-03-20 16:58:04 +00001160 except TypeError:
Raymond Hettinger6518f5e2010-12-24 00:52:54 +00001161 # Handle case with unhashable elements
Michael Foorde180d392011-01-28 19:51:48 +00001162 differences = _count_diff_all_purpose(first_seq, second_seq)
Michael Foord8442a602010-03-20 16:58:04 +00001163 else:
Michael Foorde180d392011-01-28 19:51:48 +00001164 if first == second:
Raymond Hettinger6e165b32010-11-27 09:31:37 +00001165 return
Michael Foorde180d392011-01-28 19:51:48 +00001166 differences = _count_diff_hashable(first_seq, second_seq)
Michael Foord8442a602010-03-20 16:58:04 +00001167
Raymond Hettinger93e233d2010-12-24 10:02:22 +00001168 if differences:
1169 standardMsg = 'Element counts were not equal:\n'
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001170 lines = ['First has %d, Second has %d: %r' % diff for diff in differences]
Raymond Hettinger93e233d2010-12-24 10:02:22 +00001171 diffMsg = '\n'.join(lines)
1172 standardMsg = self._truncateMessage(standardMsg, diffMsg)
1173 msg = self._formatMessage(msg, standardMsg)
1174 self.fail(msg)
Michael Foord8442a602010-03-20 16:58:04 +00001175
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001176 def assertMultiLineEqual(self, first, second, msg=None):
1177 """Assert that two multi-line strings are equal."""
Ezio Melottib3aedd42010-11-20 19:04:17 +00001178 self.assertIsInstance(first, str, 'First argument is not a string')
1179 self.assertIsInstance(second, str, 'Second argument is not a string')
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001180
1181 if first != second:
Ezio Melottiedd117f2011-04-27 10:20:38 +03001182 # don't use difflib if the strings are too long
1183 if (len(first) > self._diffThreshold or
1184 len(second) > self._diffThreshold):
1185 self._baseAssertEqual(first, second, msg)
Ezio Melottid8b509b2011-09-28 17:37:55 +03001186 firstlines = first.splitlines(keepends=True)
1187 secondlines = second.splitlines(keepends=True)
Michael Foordc653ce32010-07-10 13:52:22 +00001188 if len(firstlines) == 1 and first.strip('\r\n') == first:
1189 firstlines = [first + '\n']
1190 secondlines = [second + '\n']
Serhiy Storchaka77622f52013-09-23 23:07:00 +03001191 standardMsg = '%s != %s' % _common_shorten_repr(first, second)
Michael Foordc653ce32010-07-10 13:52:22 +00001192 diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines))
Michael Foordcb11b252010-06-05 13:14:43 +00001193 standardMsg = self._truncateMessage(standardMsg, diff)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001194 self.fail(self._formatMessage(msg, standardMsg))
1195
1196 def assertLess(self, a, b, msg=None):
1197 """Just like self.assertTrue(a < b), but with a nicer default message."""
1198 if not a < b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001199 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001200 self.fail(self._formatMessage(msg, standardMsg))
1201
1202 def assertLessEqual(self, a, b, msg=None):
1203 """Just like self.assertTrue(a <= b), but with a nicer default message."""
1204 if not a <= b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001205 standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001206 self.fail(self._formatMessage(msg, standardMsg))
1207
1208 def assertGreater(self, a, b, msg=None):
1209 """Just like self.assertTrue(a > b), but with a nicer default message."""
1210 if not a > b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001211 standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001212 self.fail(self._formatMessage(msg, standardMsg))
1213
1214 def assertGreaterEqual(self, a, b, msg=None):
1215 """Just like self.assertTrue(a >= b), but with a nicer default message."""
1216 if not a >= b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001217 standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001218 self.fail(self._formatMessage(msg, standardMsg))
1219
1220 def assertIsNone(self, obj, msg=None):
1221 """Same as self.assertTrue(obj is None), with a nicer default message."""
1222 if obj is not None:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001223 standardMsg = '%s is not None' % (safe_repr(obj),)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001224 self.fail(self._formatMessage(msg, standardMsg))
1225
1226 def assertIsNotNone(self, obj, msg=None):
1227 """Included for symmetry with assertIsNone."""
1228 if obj is None:
1229 standardMsg = 'unexpectedly None'
1230 self.fail(self._formatMessage(msg, standardMsg))
1231
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001232 def assertIsInstance(self, obj, cls, msg=None):
1233 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
1234 default message."""
1235 if not isinstance(obj, cls):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001236 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001237 self.fail(self._formatMessage(msg, standardMsg))
1238
1239 def assertNotIsInstance(self, obj, cls, msg=None):
1240 """Included for symmetry with assertIsInstance."""
1241 if isinstance(obj, cls):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001242 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001243 self.fail(self._formatMessage(msg, standardMsg))
1244
Ezio Melottied3a7d22010-12-01 02:32:32 +00001245 def assertRaisesRegex(self, expected_exception, expected_regex,
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001246 *args, **kwargs):
Ezio Melottied3a7d22010-12-01 02:32:32 +00001247 """Asserts that the message in a raised exception matches a regex.
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001248
1249 Args:
1250 expected_exception: Exception class expected to be raised.
Ezio Melottied3a7d22010-12-01 02:32:32 +00001251 expected_regex: Regex (re pattern object or string) expected
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001252 to be found in error message.
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001253 args: Function to be called and extra positional args.
1254 kwargs: Extra kwargs.
Ezio Melottib4dc2502011-05-06 15:01:41 +03001255 msg: Optional message used in case of failure. Can only be used
1256 when assertRaisesRegex is used as a context manager.
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001257 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001258 context = _AssertRaisesContext(expected_exception, self, expected_regex)
1259 return context.handle('assertRaisesRegex', args, kwargs)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001260
Ezio Melottied3a7d22010-12-01 02:32:32 +00001261 def assertWarnsRegex(self, expected_warning, expected_regex,
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001262 *args, **kwargs):
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001263 """Asserts that the message in a triggered warning matches a regexp.
1264 Basic functioning is similar to assertWarns() with the addition
1265 that only warnings whose messages also match the regular expression
1266 are considered successful matches.
1267
1268 Args:
1269 expected_warning: Warning class expected to be triggered.
Ezio Melottied3a7d22010-12-01 02:32:32 +00001270 expected_regex: Regex (re pattern object or string) expected
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001271 to be found in error message.
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001272 args: Function to be called and extra positional args.
1273 kwargs: Extra kwargs.
Ezio Melottib4dc2502011-05-06 15:01:41 +03001274 msg: Optional message used in case of failure. Can only be used
1275 when assertWarnsRegex is used as a context manager.
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001276 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001277 context = _AssertWarnsContext(expected_warning, self, expected_regex)
1278 return context.handle('assertWarnsRegex', args, kwargs)
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001279
Ezio Melottied3a7d22010-12-01 02:32:32 +00001280 def assertRegex(self, text, expected_regex, msg=None):
Michael Foorde3ef5f12010-05-08 16:46:14 +00001281 """Fail the test unless the text matches the regular expression."""
Ezio Melottied3a7d22010-12-01 02:32:32 +00001282 if isinstance(expected_regex, (str, bytes)):
Gregory P. Smithed16bf42010-12-16 19:23:05 +00001283 assert expected_regex, "expected_regex must not be empty."
Ezio Melottied3a7d22010-12-01 02:32:32 +00001284 expected_regex = re.compile(expected_regex)
1285 if not expected_regex.search(text):
Robert Collinsbe6caca2015-08-20 11:13:09 +12001286 standardMsg = "Regex didn't match: %r not found in %r" % (
1287 expected_regex.pattern, text)
1288 # _formatMessage ensures the longMessage option is respected
1289 msg = self._formatMessage(msg, standardMsg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001290 raise self.failureException(msg)
1291
Ezio Melotti8f776302010-12-10 02:32:05 +00001292 def assertNotRegex(self, text, unexpected_regex, msg=None):
Michael Foorde3ef5f12010-05-08 16:46:14 +00001293 """Fail the test if the text matches the regular expression."""
Ezio Melottied3a7d22010-12-01 02:32:32 +00001294 if isinstance(unexpected_regex, (str, bytes)):
1295 unexpected_regex = re.compile(unexpected_regex)
1296 match = unexpected_regex.search(text)
Benjamin Petersonb48af542010-04-11 20:43:16 +00001297 if match:
Robert Collinsbe6caca2015-08-20 11:13:09 +12001298 standardMsg = 'Regex matched: %r matches %r in %r' % (
1299 text[match.start() : match.end()],
1300 unexpected_regex.pattern,
1301 text)
1302 # _formatMessage ensures the longMessage option is respected
1303 msg = self._formatMessage(msg, standardMsg)
Benjamin Petersonb48af542010-04-11 20:43:16 +00001304 raise self.failureException(msg)
1305
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001306
Ezio Melottied3a7d22010-12-01 02:32:32 +00001307 def _deprecate(original_func):
1308 def deprecated_func(*args, **kwargs):
1309 warnings.warn(
1310 'Please use {0} instead.'.format(original_func.__name__),
1311 DeprecationWarning, 2)
1312 return original_func(*args, **kwargs)
1313 return deprecated_func
1314
Ezio Melotti361467e2011-04-03 17:37:58 +03001315 # see #9424
Ezio Melotti0f535012011-04-03 18:02:13 +03001316 failUnlessEqual = assertEquals = _deprecate(assertEqual)
1317 failIfEqual = assertNotEquals = _deprecate(assertNotEqual)
1318 failUnlessAlmostEqual = assertAlmostEquals = _deprecate(assertAlmostEqual)
1319 failIfAlmostEqual = assertNotAlmostEquals = _deprecate(assertNotAlmostEqual)
1320 failUnless = assert_ = _deprecate(assertTrue)
1321 failUnlessRaises = _deprecate(assertRaises)
1322 failIf = _deprecate(assertFalse)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001323 assertRaisesRegexp = _deprecate(assertRaisesRegex)
1324 assertRegexpMatches = _deprecate(assertRegex)
Robert Collinsbe6caca2015-08-20 11:13:09 +12001325 assertNotRegexpMatches = _deprecate(assertNotRegex)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001326
1327
1328
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001329class FunctionTestCase(TestCase):
1330 """A test case that wraps a test function.
1331
1332 This is useful for slipping pre-existing test functions into the
1333 unittest framework. Optionally, set-up and tidy-up functions can be
1334 supplied. As with TestCase, the tidy-up ('tearDown') function will
1335 always be called if the set-up ('setUp') function ran successfully.
1336 """
1337
1338 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
1339 super(FunctionTestCase, self).__init__()
1340 self._setUpFunc = setUp
1341 self._tearDownFunc = tearDown
1342 self._testFunc = testFunc
1343 self._description = description
1344
1345 def setUp(self):
1346 if self._setUpFunc is not None:
1347 self._setUpFunc()
1348
1349 def tearDown(self):
1350 if self._tearDownFunc is not None:
1351 self._tearDownFunc()
1352
1353 def runTest(self):
1354 self._testFunc()
1355
1356 def id(self):
1357 return self._testFunc.__name__
1358
1359 def __eq__(self, other):
1360 if not isinstance(other, self.__class__):
1361 return NotImplemented
1362
1363 return self._setUpFunc == other._setUpFunc and \
1364 self._tearDownFunc == other._tearDownFunc and \
1365 self._testFunc == other._testFunc and \
1366 self._description == other._description
1367
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001368 def __hash__(self):
1369 return hash((type(self), self._setUpFunc, self._tearDownFunc,
1370 self._testFunc, self._description))
1371
1372 def __str__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001373 return "%s (%s)" % (strclass(self.__class__),
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001374 self._testFunc.__name__)
1375
1376 def __repr__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001377 return "<%s tec=%s>" % (strclass(self.__class__),
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001378 self._testFunc)
1379
1380 def shortDescription(self):
1381 if self._description is not None:
1382 return self._description
1383 doc = self._testFunc.__doc__
1384 return doc and doc.split("\n")[0].strip() or None
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +01001385
1386
1387class _SubTest(TestCase):
1388
1389 def __init__(self, test_case, message, params):
1390 super().__init__()
1391 self._message = message
1392 self.test_case = test_case
1393 self.params = params
1394 self.failureException = test_case.failureException
1395
1396 def runTest(self):
1397 raise NotImplementedError("subtests cannot be run directly")
1398
1399 def _subDescription(self):
1400 parts = []
Berker Peksag16ea19f2016-09-21 19:34:15 +03001401 if self._message is not _subtest_msg_sentinel:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +01001402 parts.append("[{}]".format(self._message))
1403 if self.params:
1404 params_desc = ', '.join(
1405 "{}={!r}".format(k, v)
1406 for (k, v) in sorted(self.params.items()))
1407 parts.append("({})".format(params_desc))
1408 return " ".join(parts) or '(<subtest>)'
1409
1410 def id(self):
1411 return "{} {}".format(self.test_case.id(), self._subDescription())
1412
1413 def shortDescription(self):
1414 """Returns a one-line description of the subtest, or None if no
1415 description has been provided.
1416 """
1417 return self.test_case.shortDescription()
1418
1419 def __str__(self):
1420 return "{} {}".format(self.test_case, self._subDescription())