blob: 993aaec1940748cd3b00d2e4cb835a22eb9c0c30 [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 Storchakadf573d62015-05-16 16:29:50 +0300156 try:
Victor Stinnerbbd3cf82017-03-28 00:56:28 +0200157 if not _is_subtype(self.expected, self._base_type):
158 raise TypeError('%s() arg 1 must be %s' %
159 (name, self._base_type_str))
160 if args and args[0] is None:
161 warnings.warn("callable is None",
162 DeprecationWarning, 3)
163 args = ()
164 if not args:
165 self.msg = kwargs.pop('msg', None)
166 if kwargs:
167 warnings.warn('%r is an invalid keyword argument for '
168 'this function' % next(iter(kwargs)),
169 DeprecationWarning, 3)
170 return self
171
172 callable_obj, *args = args
173 try:
174 self.obj_name = callable_obj.__name__
175 except AttributeError:
176 self.obj_name = str(callable_obj)
177 with self:
178 callable_obj(*args, **kwargs)
179 finally:
180 # bpo-23890: manually break a reference cycle
181 self = None
Ezio Melottib4dc2502011-05-06 15:01:41 +0300182
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000183
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000184class _AssertRaisesContext(_AssertRaisesBaseContext):
185 """A context manager used to implement TestCase.assertRaises* methods."""
186
Serhiy Storchaka041dd8e2015-05-21 20:15:40 +0300187 _base_type = BaseException
188 _base_type_str = 'an exception type or tuple of exception types'
189
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000190 def __enter__(self):
Ezio Melotti49008232010-02-08 21:57:48 +0000191 return self
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000192
193 def __exit__(self, exc_type, exc_value, tb):
194 if exc_type is None:
195 try:
196 exc_name = self.expected.__name__
197 except AttributeError:
198 exc_name = str(self.expected)
199 if self.obj_name:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300200 self._raiseFailure("{} not raised by {}".format(exc_name,
201 self.obj_name))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000202 else:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300203 self._raiseFailure("{} not raised".format(exc_name))
Antoine Pitrou96810222014-04-29 01:23:50 +0200204 else:
205 traceback.clear_frames(tb)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000206 if not issubclass(exc_type, self.expected):
207 # let unexpected exceptions pass through
208 return False
Ezio Melotti49008232010-02-08 21:57:48 +0000209 # store exception, without traceback, for later retrieval
210 self.exception = exc_value.with_traceback(None)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000211 if self.expected_regex is None:
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000212 return True
213
Ezio Melottied3a7d22010-12-01 02:32:32 +0000214 expected_regex = self.expected_regex
215 if not expected_regex.search(str(exc_value)):
Ezio Melottib4dc2502011-05-06 15:01:41 +0300216 self._raiseFailure('"{}" does not match "{}"'.format(
217 expected_regex.pattern, str(exc_value)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000218 return True
219
220
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000221class _AssertWarnsContext(_AssertRaisesBaseContext):
222 """A context manager used to implement TestCase.assertWarns* methods."""
223
Serhiy Storchaka041dd8e2015-05-21 20:15:40 +0300224 _base_type = Warning
225 _base_type_str = 'a warning type or tuple of warning types'
226
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000227 def __enter__(self):
228 # The __warningregistry__'s need to be in a pristine state for tests
229 # to work properly.
230 for v in sys.modules.values():
231 if getattr(v, '__warningregistry__', None):
232 v.__warningregistry__ = {}
233 self.warnings_manager = warnings.catch_warnings(record=True)
234 self.warnings = self.warnings_manager.__enter__()
235 warnings.simplefilter("always", self.expected)
236 return self
237
238 def __exit__(self, exc_type, exc_value, tb):
239 self.warnings_manager.__exit__(exc_type, exc_value, tb)
240 if exc_type is not None:
241 # let unexpected exceptions pass through
242 return
243 try:
244 exc_name = self.expected.__name__
245 except AttributeError:
246 exc_name = str(self.expected)
247 first_matching = None
248 for m in self.warnings:
249 w = m.message
250 if not isinstance(w, self.expected):
251 continue
252 if first_matching is None:
253 first_matching = w
Ezio Melottied3a7d22010-12-01 02:32:32 +0000254 if (self.expected_regex is not None and
255 not self.expected_regex.search(str(w))):
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000256 continue
257 # store warning for later retrieval
258 self.warning = w
259 self.filename = m.filename
260 self.lineno = m.lineno
261 return
262 # Now we simply try to choose a helpful failure message
263 if first_matching is not None:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300264 self._raiseFailure('"{}" does not match "{}"'.format(
265 self.expected_regex.pattern, str(first_matching)))
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000266 if self.obj_name:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300267 self._raiseFailure("{} not triggered by {}".format(exc_name,
268 self.obj_name))
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000269 else:
Ezio Melottib4dc2502011-05-06 15:01:41 +0300270 self._raiseFailure("{} not triggered".format(exc_name))
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000271
272
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200273
274_LoggingWatcher = collections.namedtuple("_LoggingWatcher",
275 ["records", "output"])
276
277
278class _CapturingHandler(logging.Handler):
279 """
280 A logging handler capturing all (raw and formatted) logging output.
281 """
282
283 def __init__(self):
284 logging.Handler.__init__(self)
285 self.watcher = _LoggingWatcher([], [])
286
287 def flush(self):
288 pass
289
290 def emit(self, record):
291 self.watcher.records.append(record)
292 msg = self.format(record)
293 self.watcher.output.append(msg)
294
295
296
297class _AssertLogsContext(_BaseTestCaseContext):
298 """A context manager used to implement TestCase.assertLogs()."""
299
300 LOGGING_FORMAT = "%(levelname)s:%(name)s:%(message)s"
301
302 def __init__(self, test_case, logger_name, level):
303 _BaseTestCaseContext.__init__(self, test_case)
304 self.logger_name = logger_name
305 if level:
306 self.level = logging._nameToLevel.get(level, level)
307 else:
308 self.level = logging.INFO
309 self.msg = None
310
311 def __enter__(self):
312 if isinstance(self.logger_name, logging.Logger):
313 logger = self.logger = self.logger_name
314 else:
315 logger = self.logger = logging.getLogger(self.logger_name)
316 formatter = logging.Formatter(self.LOGGING_FORMAT)
317 handler = _CapturingHandler()
318 handler.setFormatter(formatter)
319 self.watcher = handler.watcher
320 self.old_handlers = logger.handlers[:]
321 self.old_level = logger.level
322 self.old_propagate = logger.propagate
323 logger.handlers = [handler]
324 logger.setLevel(self.level)
325 logger.propagate = False
326 return handler.watcher
327
328 def __exit__(self, exc_type, exc_value, tb):
329 self.logger.handlers = self.old_handlers
330 self.logger.propagate = self.old_propagate
331 self.logger.setLevel(self.old_level)
332 if exc_type is not None:
333 # let unexpected exceptions pass through
334 return False
335 if len(self.watcher.records) == 0:
336 self._raiseFailure(
337 "no logs of level {} or higher triggered on {}"
338 .format(logging.getLevelName(self.level), self.logger.name))
339
340
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000341class TestCase(object):
342 """A class whose instances are single test cases.
343
344 By default, the test code itself should be placed in a method named
345 'runTest'.
346
347 If the fixture may be used for many test cases, create as
348 many test methods as are needed. When instantiating such a TestCase
349 subclass, specify in the constructor arguments the name of the test method
350 that the instance is to execute.
351
352 Test authors should subclass TestCase for their own tests. Construction
353 and deconstruction of the test's environment ('fixture') can be
354 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
355
356 If it is necessary to override the __init__ method, the base class
357 __init__ method must always be called. It is important that subclasses
358 should not change the signature of their __init__ method, since instances
359 of the classes are instantiated automatically by parts of the framework
360 in order to be run.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000361
Ezio Melotti31797e52013-03-29 03:42:29 +0200362 When subclassing TestCase, you can set these attributes:
363 * failureException: determines which exception will be raised when
364 the instance's assertion methods fail; test methods raising this
365 exception will be deemed to have 'failed' rather than 'errored'.
366 * longMessage: determines whether long messages (including repr of
367 objects used in assert methods) will be printed on failure in *addition*
368 to any explicit message passed.
369 * maxDiff: sets the maximum length of a diff in failure messages
370 by assert methods using difflib. It is looked up as an instance
371 attribute so can be configured by individual tests if required.
372 """
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000373
374 failureException = AssertionError
375
Michael Foord5074df62010-12-03 00:53:09 +0000376 longMessage = True
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000377
Michael Foord085dfd32010-06-05 12:17:02 +0000378 maxDiff = 80*8
379
Ezio Melottiedd117f2011-04-27 10:20:38 +0300380 # If a string is longer than _diffThreshold, use normal comparison instead
381 # of difflib. See #11763.
382 _diffThreshold = 2**16
383
Benjamin Peterson847a4112010-03-14 15:04:17 +0000384 # Attribute used by TestSuite for classSetUp
385
386 _classSetupFailed = False
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000387
388 def __init__(self, methodName='runTest'):
389 """Create an instance of the class that will use the named test
390 method when executed. Raises a ValueError if the instance does
391 not have a method with the specified name.
392 """
393 self._testMethodName = methodName
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100394 self._outcome = None
Michael Foord32e1d832011-01-03 17:00:11 +0000395 self._testMethodDoc = 'No test'
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000396 try:
397 testMethod = getattr(self, methodName)
398 except AttributeError:
Michael Foord32e1d832011-01-03 17:00:11 +0000399 if methodName != 'runTest':
400 # we allow instantiation with no explicit method name
401 # but not an *incorrect* or missing method name
402 raise ValueError("no such test method in %s: %s" %
403 (self.__class__, methodName))
404 else:
405 self._testMethodDoc = testMethod.__doc__
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000406 self._cleanups = []
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100407 self._subtest = None
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000408
409 # Map types to custom assertEqual functions that will compare
410 # instances of said type in more detail to generate a more useful
411 # error message.
Benjamin Peterson34b2b262011-07-12 19:21:42 -0500412 self._type_equality_funcs = {}
Michael Foord8ca6d982010-11-20 15:34:26 +0000413 self.addTypeEqualityFunc(dict, 'assertDictEqual')
414 self.addTypeEqualityFunc(list, 'assertListEqual')
415 self.addTypeEqualityFunc(tuple, 'assertTupleEqual')
416 self.addTypeEqualityFunc(set, 'assertSetEqual')
417 self.addTypeEqualityFunc(frozenset, 'assertSetEqual')
418 self.addTypeEqualityFunc(str, 'assertMultiLineEqual')
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000419
420 def addTypeEqualityFunc(self, typeobj, function):
421 """Add a type specific assertEqual style function to compare a type.
422
423 This method is for use by TestCase subclasses that need to register
424 their own type equality functions to provide nicer error messages.
425
426 Args:
427 typeobj: The data type to call this function on when both values
428 are of the same type in assertEqual().
429 function: The callable taking two arguments and an optional
430 msg= argument that raises self.failureException with a
431 useful error message when the two arguments are not equal.
432 """
Benjamin Peterson8f326b22009-12-13 02:10:36 +0000433 self._type_equality_funcs[typeobj] = function
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000434
435 def addCleanup(self, function, *args, **kwargs):
436 """Add a function, with arguments, to be called when the test is
437 completed. Functions added are called on a LIFO basis and are
438 called after tearDown on test failure or success.
439
440 Cleanup items are called even if setUp fails (unlike tearDown)."""
441 self._cleanups.append((function, args, kwargs))
442
443 def setUp(self):
444 "Hook method for setting up the test fixture before exercising it."
445 pass
446
447 def tearDown(self):
448 "Hook method for deconstructing the test fixture after testing it."
449 pass
450
Benjamin Peterson847a4112010-03-14 15:04:17 +0000451 @classmethod
452 def setUpClass(cls):
453 "Hook method for setting up class fixture before running tests in the class."
454
455 @classmethod
456 def tearDownClass(cls):
457 "Hook method for deconstructing the class fixture after running all tests in the class."
458
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000459 def countTestCases(self):
460 return 1
461
462 def defaultTestResult(self):
463 return result.TestResult()
464
465 def shortDescription(self):
Michael Foord34c94622010-02-10 15:51:42 +0000466 """Returns a one-line description of the test, or None if no
467 description has been provided.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000468
Michael Foord34c94622010-02-10 15:51:42 +0000469 The default implementation of this method returns the first line of
470 the specified test method's docstring.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000471 """
Michael Foord34c94622010-02-10 15:51:42 +0000472 doc = self._testMethodDoc
473 return doc and doc.split("\n")[0].strip() or None
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000474
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000475
476 def id(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000477 return "%s.%s" % (strclass(self.__class__), self._testMethodName)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000478
479 def __eq__(self, other):
480 if type(self) is not type(other):
481 return NotImplemented
482
483 return self._testMethodName == other._testMethodName
484
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000485 def __hash__(self):
486 return hash((type(self), self._testMethodName))
487
488 def __str__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000489 return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000490
491 def __repr__(self):
492 return "<%s testMethod=%s>" % \
Benjamin Peterson847a4112010-03-14 15:04:17 +0000493 (strclass(self.__class__), self._testMethodName)
494
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100495 def _addSkip(self, result, test_case, reason):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000496 addSkip = getattr(result, 'addSkip', None)
497 if addSkip is not None:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100498 addSkip(test_case, reason)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000499 else:
500 warnings.warn("TestResult has no addSkip method, skips not reported",
501 RuntimeWarning, 2)
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100502 result.addSuccess(test_case)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000503
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100504 @contextlib.contextmanager
Berker Peksag16ea19f2016-09-21 19:34:15 +0300505 def subTest(self, msg=_subtest_msg_sentinel, **params):
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100506 """Return a context manager that will return the enclosed block
507 of code in a subtest identified by the optional message and
508 keyword parameters. A failure in the subtest marks the test
509 case as failed but resumes execution at the end of the enclosed
510 block, allowing further test code to be executed.
511 """
512 if not self._outcome.result_supports_subtests:
513 yield
514 return
515 parent = self._subtest
516 if parent is None:
517 params_map = collections.ChainMap(params)
518 else:
519 params_map = parent.params.new_child(params)
520 self._subtest = _SubTest(self, msg, params_map)
Michael Foordb3468f72010-12-19 03:19:47 +0000521 try:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100522 with self._outcome.testPartExecutor(self._subtest, isTest=True):
523 yield
524 if not self._outcome.success:
525 result = self._outcome.result
526 if result is not None and result.failfast:
527 raise _ShouldStop
528 elif self._outcome.expectedFailure:
529 # If the test is expecting a failure, we really want to
530 # stop now and register the expected failure.
531 raise _ShouldStop
532 finally:
533 self._subtest = parent
534
535 def _feedErrorsToResult(self, result, errors):
536 for test, exc_info in errors:
537 if isinstance(test, _SubTest):
538 result.addSubTest(test.test_case, test, exc_info)
539 elif exc_info is not None:
540 if issubclass(exc_info[0], self.failureException):
541 result.addFailure(test, exc_info)
542 else:
543 result.addError(test, exc_info)
544
545 def _addExpectedFailure(self, result, exc_info):
546 try:
547 addExpectedFailure = result.addExpectedFailure
548 except AttributeError:
549 warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
550 RuntimeWarning)
551 result.addSuccess(self)
552 else:
553 addExpectedFailure(self, exc_info)
554
555 def _addUnexpectedSuccess(self, result):
556 try:
557 addUnexpectedSuccess = result.addUnexpectedSuccess
558 except AttributeError:
559 warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failure",
560 RuntimeWarning)
561 # We need to pass an actual exception and traceback to addFailure,
562 # otherwise the legacy result can choke.
563 try:
564 raise _UnexpectedSuccess from None
565 except _UnexpectedSuccess:
566 result.addFailure(self, sys.exc_info())
567 else:
568 addUnexpectedSuccess(self)
Michael Foordb3468f72010-12-19 03:19:47 +0000569
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000570 def run(self, result=None):
571 orig_result = result
572 if result is None:
573 result = self.defaultTestResult()
574 startTestRun = getattr(result, 'startTestRun', None)
575 if startTestRun is not None:
576 startTestRun()
577
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000578 result.startTest(self)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000579
580 testMethod = getattr(self, self._testMethodName)
581 if (getattr(self.__class__, "__unittest_skip__", False) or
582 getattr(testMethod, "__unittest_skip__", False)):
583 # If the class or method was skipped.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000584 try:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000585 skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
586 or getattr(testMethod, '__unittest_skip_why__', ''))
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100587 self._addSkip(result, self, skip_why)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000588 finally:
589 result.stopTest(self)
590 return
Robert Collinsed599b72015-08-28 10:34:51 +1200591 expecting_failure_method = getattr(testMethod,
592 "__unittest_expecting_failure__", False)
593 expecting_failure_class = getattr(self,
594 "__unittest_expecting_failure__", False)
595 expecting_failure = expecting_failure_class or expecting_failure_method
Victor Stinner031bd532013-12-09 01:52:50 +0100596 outcome = _Outcome(result)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000597 try:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100598 self._outcome = outcome
Michael Foordb3468f72010-12-19 03:19:47 +0000599
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100600 with outcome.testPartExecutor(self):
601 self.setUp()
Michael Foordb3468f72010-12-19 03:19:47 +0000602 if outcome.success:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100603 outcome.expecting_failure = expecting_failure
604 with outcome.testPartExecutor(self, isTest=True):
605 testMethod()
606 outcome.expecting_failure = False
607 with outcome.testPartExecutor(self):
608 self.tearDown()
Michael Foordb3468f72010-12-19 03:19:47 +0000609
610 self.doCleanups()
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100611 for test, reason in outcome.skipped:
612 self._addSkip(result, test, reason)
613 self._feedErrorsToResult(result, outcome.errors)
Michael Foordb3468f72010-12-19 03:19:47 +0000614 if outcome.success:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100615 if expecting_failure:
616 if outcome.expectedFailure:
617 self._addExpectedFailure(result, outcome.expectedFailure)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000618 else:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100619 self._addUnexpectedSuccess(result)
620 else:
621 result.addSuccess(self)
Michael Foord1341bb02011-03-14 19:01:46 -0400622 return result
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000623 finally:
624 result.stopTest(self)
625 if orig_result is None:
626 stopTestRun = getattr(result, 'stopTestRun', None)
627 if stopTestRun is not None:
628 stopTestRun()
629
Victor Stinner031bd532013-12-09 01:52:50 +0100630 # explicitly break reference cycles:
631 # outcome.errors -> frame -> outcome -> outcome.errors
632 # outcome.expectedFailure -> frame -> outcome -> outcome.expectedFailure
633 outcome.errors.clear()
634 outcome.expectedFailure = None
635
636 # clear the outcome, no more needed
637 self._outcome = None
638
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000639 def doCleanups(self):
640 """Execute all cleanup functions. Normally called for you after
641 tearDown."""
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100642 outcome = self._outcome or _Outcome()
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000643 while self._cleanups:
Michael Foordb3468f72010-12-19 03:19:47 +0000644 function, args, kwargs = self._cleanups.pop()
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +0100645 with outcome.testPartExecutor(self):
646 function(*args, **kwargs)
Michael Foordb3468f72010-12-19 03:19:47 +0000647
648 # return this for backwards compatibility
649 # even though we no longer us it internally
650 return outcome.success
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000651
652 def __call__(self, *args, **kwds):
653 return self.run(*args, **kwds)
654
655 def debug(self):
656 """Run the test without collecting errors in a TestResult"""
657 self.setUp()
658 getattr(self, self._testMethodName)()
659 self.tearDown()
Michael Foordb8748742010-06-10 16:16:08 +0000660 while self._cleanups:
661 function, args, kwargs = self._cleanups.pop(-1)
662 function(*args, **kwargs)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000663
664 def skipTest(self, reason):
665 """Skip this test."""
666 raise SkipTest(reason)
667
668 def fail(self, msg=None):
669 """Fail immediately, with the given message."""
670 raise self.failureException(msg)
671
672 def assertFalse(self, expr, msg=None):
Ezio Melotti3044fa72010-12-18 17:31:58 +0000673 """Check that the expression is false."""
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000674 if expr:
Ezio Melotti3044fa72010-12-18 17:31:58 +0000675 msg = self._formatMessage(msg, "%s is not false" % safe_repr(expr))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000676 raise self.failureException(msg)
677
678 def assertTrue(self, expr, msg=None):
Ezio Melotti3044fa72010-12-18 17:31:58 +0000679 """Check that the expression is true."""
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000680 if not expr:
Ezio Melotti3044fa72010-12-18 17:31:58 +0000681 msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000682 raise self.failureException(msg)
683
684 def _formatMessage(self, msg, standardMsg):
685 """Honour the longMessage attribute when generating failure messages.
686 If longMessage is False this means:
687 * Use only an explicit message if it is provided
688 * Otherwise use the standard message for the assert
689
690 If longMessage is True:
691 * Use the standard message
692 * If an explicit message is provided, plus ' : ' and the explicit message
693 """
694 if not self.longMessage:
695 return msg or standardMsg
696 if msg is None:
697 return standardMsg
Benjamin Peterson847a4112010-03-14 15:04:17 +0000698 try:
699 # don't switch to '{}' formatting in Python 2.X
700 # it changes the way unicode input is handled
701 return '%s : %s' % (standardMsg, msg)
702 except UnicodeDecodeError:
703 return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000704
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300705 def assertRaises(self, expected_exception, *args, **kwargs):
706 """Fail unless an exception of class expected_exception is raised
707 by the callable when invoked with specified positional and
708 keyword arguments. If a different type of exception is
Andrew Svetlov737fb892012-12-18 21:14:22 +0200709 raised, it will not be caught, and the test case will be
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000710 deemed to have suffered an error, exactly as for an
711 unexpected exception.
712
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300713 If called with the callable and arguments omitted, will return a
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000714 context object used like this::
715
Michael Foord1c42b122010-02-05 22:58:21 +0000716 with self.assertRaises(SomeException):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000717 do_something()
Michael Foord1c42b122010-02-05 22:58:21 +0000718
Ezio Melottib4dc2502011-05-06 15:01:41 +0300719 An optional keyword argument 'msg' can be provided when assertRaises
720 is used as a context object.
721
Michael Foord1c42b122010-02-05 22:58:21 +0000722 The context manager keeps a reference to the exception as
Ezio Melotti49008232010-02-08 21:57:48 +0000723 the 'exception' attribute. This allows you to inspect the
Michael Foord1c42b122010-02-05 22:58:21 +0000724 exception after the assertion::
725
726 with self.assertRaises(SomeException) as cm:
727 do_something()
Ezio Melotti49008232010-02-08 21:57:48 +0000728 the_exception = cm.exception
Michael Foordb57ac6d2010-02-05 23:26:29 +0000729 self.assertEqual(the_exception.error_code, 3)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000730 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300731 context = _AssertRaisesContext(expected_exception, self)
Victor Stinnerbbd3cf82017-03-28 00:56:28 +0200732 try:
733 return context.handle('assertRaises', args, kwargs)
734 finally:
735 # bpo-23890: manually break a reference cycle
736 context = None
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000737
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300738 def assertWarns(self, expected_warning, *args, **kwargs):
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000739 """Fail unless a warning of class warnClass is triggered
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300740 by the callable when invoked with specified positional and
741 keyword arguments. If a different type of warning is
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000742 triggered, it will not be handled: depending on the other
743 warning filtering rules in effect, it might be silenced, printed
744 out, or raised as an exception.
745
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300746 If called with the callable and arguments omitted, will return a
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000747 context object used like this::
748
749 with self.assertWarns(SomeWarning):
750 do_something()
751
Ezio Melottib4dc2502011-05-06 15:01:41 +0300752 An optional keyword argument 'msg' can be provided when assertWarns
753 is used as a context object.
754
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000755 The context manager keeps a reference to the first matching
756 warning as the 'warning' attribute; similarly, the 'filename'
757 and 'lineno' attributes give you information about the line
758 of Python code from which the warning was triggered.
759 This allows you to inspect the warning after the assertion::
760
761 with self.assertWarns(SomeWarning) as cm:
762 do_something()
763 the_warning = cm.warning
764 self.assertEqual(the_warning.some_attribute, 147)
765 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +0300766 context = _AssertWarnsContext(expected_warning, self)
767 return context.handle('assertWarns', args, kwargs)
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +0000768
Antoine Pitrou0715b9f2013-09-14 19:45:47 +0200769 def assertLogs(self, logger=None, level=None):
770 """Fail unless a log message of level *level* or higher is emitted
771 on *logger_name* or its children. If omitted, *level* defaults to
772 INFO and *logger* defaults to the root logger.
773
774 This method must be used as a context manager, and will yield
775 a recording object with two attributes: `output` and `records`.
776 At the end of the context manager, the `output` attribute will
777 be a list of the matching formatted log messages and the
778 `records` attribute will be a list of the corresponding LogRecord
779 objects.
780
781 Example::
782
783 with self.assertLogs('foo', level='INFO') as cm:
784 logging.getLogger('foo').info('first message')
785 logging.getLogger('foo.bar').error('second message')
786 self.assertEqual(cm.output, ['INFO:foo:first message',
787 'ERROR:foo.bar:second message'])
788 """
789 return _AssertLogsContext(self, logger, level)
790
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000791 def _getAssertEqualityFunc(self, first, second):
792 """Get a detailed comparison function for the types of the two args.
793
794 Returns: A callable accepting (first, second, msg=None) that will
795 raise a failure exception if first != second with a useful human
796 readable error message for those types.
797 """
798 #
799 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
800 # and vice versa. I opted for the conservative approach in case
801 # subclasses are not intended to be compared in detail to their super
802 # class instances using a type equality func. This means testing
803 # subtypes won't automagically use the detailed comparison. Callers
804 # should use their type specific assertSpamEqual method to compare
805 # subclasses if the detailed comparison is desired and appropriate.
806 # See the discussion in http://bugs.python.org/issue2578.
807 #
808 if type(first) is type(second):
809 asserter = self._type_equality_funcs.get(type(first))
810 if asserter is not None:
Benjamin Peterson34b2b262011-07-12 19:21:42 -0500811 if isinstance(asserter, str):
812 asserter = getattr(self, asserter)
Benjamin Peterson8f326b22009-12-13 02:10:36 +0000813 return asserter
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000814
815 return self._baseAssertEqual
816
817 def _baseAssertEqual(self, first, second, msg=None):
818 """The default assertEqual implementation, not type specific."""
819 if not first == second:
Serhiy Storchaka77622f52013-09-23 23:07:00 +0300820 standardMsg = '%s != %s' % _common_shorten_repr(first, second)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000821 msg = self._formatMessage(msg, standardMsg)
822 raise self.failureException(msg)
823
824 def assertEqual(self, first, second, msg=None):
825 """Fail if the two objects are unequal as determined by the '=='
826 operator.
827 """
828 assertion_func = self._getAssertEqualityFunc(first, second)
829 assertion_func(first, second, msg=msg)
830
831 def assertNotEqual(self, first, second, msg=None):
Ezio Melotti90eea972012-11-08 11:08:39 +0200832 """Fail if the two objects are equal as determined by the '!='
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000833 operator.
834 """
835 if not first != second:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000836 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
837 safe_repr(second)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000838 raise self.failureException(msg)
839
Michael Foord321d0592010-11-02 13:44:51 +0000840 def assertAlmostEqual(self, first, second, places=None, msg=None,
Benjamin Petersonb48af542010-04-11 20:43:16 +0000841 delta=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000842 """Fail if the two objects are unequal as determined by their
843 difference rounded to the given number of decimal places
Benjamin Petersonb48af542010-04-11 20:43:16 +0000844 (default 7) and comparing to zero, or by comparing that the
845 between the two objects is more than the given delta.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000846
847 Note that decimal places (from zero) are usually not the same
Martin Pantereb995702016-07-28 01:11:04 +0000848 as significant digits (measured from the most significant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000849
850 If the two objects compare equal then they will automatically
851 compare almost equal.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000852 """
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000853 if first == second:
Benjamin Petersonb48af542010-04-11 20:43:16 +0000854 # shortcut
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000855 return
Benjamin Petersonb48af542010-04-11 20:43:16 +0000856 if delta is not None and places is not None:
857 raise TypeError("specify delta or places not both")
858
Giampaolo Rodola5d7a8d02017-05-01 18:18:56 +0200859 diff = abs(first - second)
Benjamin Petersonb48af542010-04-11 20:43:16 +0000860 if delta is not None:
Giampaolo Rodola5d7a8d02017-05-01 18:18:56 +0200861 if diff <= delta:
Benjamin Petersonb48af542010-04-11 20:43:16 +0000862 return
863
Giampaolo Rodola5d7a8d02017-05-01 18:18:56 +0200864 standardMsg = '%s != %s within %s delta (%s difference)' % (
865 safe_repr(first),
866 safe_repr(second),
867 safe_repr(delta),
868 safe_repr(diff))
Benjamin Petersonb48af542010-04-11 20:43:16 +0000869 else:
870 if places is None:
871 places = 7
872
Giampaolo Rodola5d7a8d02017-05-01 18:18:56 +0200873 if round(diff, places) == 0:
Benjamin Petersonb48af542010-04-11 20:43:16 +0000874 return
875
Giampaolo Rodola5d7a8d02017-05-01 18:18:56 +0200876 standardMsg = '%s != %s within %r places (%s difference)' % (
877 safe_repr(first),
878 safe_repr(second),
879 places,
880 safe_repr(diff))
Benjamin Petersonb48af542010-04-11 20:43:16 +0000881 msg = self._formatMessage(msg, standardMsg)
882 raise self.failureException(msg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000883
Michael Foord321d0592010-11-02 13:44:51 +0000884 def assertNotAlmostEqual(self, first, second, places=None, msg=None,
Benjamin Petersonb48af542010-04-11 20:43:16 +0000885 delta=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000886 """Fail if the two objects are equal as determined by their
887 difference rounded to the given number of decimal places
Benjamin Petersonb48af542010-04-11 20:43:16 +0000888 (default 7) and comparing to zero, or by comparing that the
889 between the two objects is less than the given delta.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000890
891 Note that decimal places (from zero) are usually not the same
Martin Pantereb995702016-07-28 01:11:04 +0000892 as significant digits (measured from the most significant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000893
894 Objects that are equal automatically fail.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000895 """
Benjamin Petersonb48af542010-04-11 20:43:16 +0000896 if delta is not None and places is not None:
897 raise TypeError("specify delta or places not both")
Giampaolo Rodola5d7a8d02017-05-01 18:18:56 +0200898 diff = abs(first - second)
Benjamin Petersonb48af542010-04-11 20:43:16 +0000899 if delta is not None:
Giampaolo Rodola5d7a8d02017-05-01 18:18:56 +0200900 if not (first == second) and diff > delta:
Benjamin Petersonb48af542010-04-11 20:43:16 +0000901 return
Giampaolo Rodola5d7a8d02017-05-01 18:18:56 +0200902 standardMsg = '%s == %s within %s delta (%s difference)' % (
903 safe_repr(first),
904 safe_repr(second),
905 safe_repr(delta),
906 safe_repr(diff))
Benjamin Petersonb48af542010-04-11 20:43:16 +0000907 else:
908 if places is None:
909 places = 7
Giampaolo Rodola5d7a8d02017-05-01 18:18:56 +0200910 if not (first == second) and round(diff, places) != 0:
Benjamin Petersonb48af542010-04-11 20:43:16 +0000911 return
Benjamin Peterson847a4112010-03-14 15:04:17 +0000912 standardMsg = '%s == %s within %r places' % (safe_repr(first),
Benjamin Petersonb48af542010-04-11 20:43:16 +0000913 safe_repr(second),
914 places)
915
916 msg = self._formatMessage(msg, standardMsg)
917 raise self.failureException(msg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000918
Michael Foord085dfd32010-06-05 12:17:02 +0000919 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000920 """An equality assertion for ordered sequences (like lists and tuples).
921
R. David Murrayad13f222010-01-29 22:17:58 +0000922 For the purposes of this function, a valid ordered sequence type is one
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000923 which can be indexed, has a length, and has an equality operator.
924
925 Args:
926 seq1: The first sequence to compare.
927 seq2: The second sequence to compare.
928 seq_type: The expected datatype of the sequences, or None if no
929 datatype should be enforced.
930 msg: Optional message to use on failure instead of a list of
931 differences.
932 """
Benjamin Petersonb29614e2012-10-09 11:16:03 -0400933 if seq_type is not None:
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000934 seq_type_name = seq_type.__name__
935 if not isinstance(seq1, seq_type):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000936 raise self.failureException('First sequence is not a %s: %s'
937 % (seq_type_name, safe_repr(seq1)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000938 if not isinstance(seq2, seq_type):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000939 raise self.failureException('Second sequence is not a %s: %s'
940 % (seq_type_name, safe_repr(seq2)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000941 else:
942 seq_type_name = "sequence"
943
944 differing = None
945 try:
946 len1 = len(seq1)
947 except (TypeError, NotImplementedError):
948 differing = 'First %s has no length. Non-sequence?' % (
949 seq_type_name)
950
951 if differing is None:
952 try:
953 len2 = len(seq2)
954 except (TypeError, NotImplementedError):
955 differing = 'Second %s has no length. Non-sequence?' % (
956 seq_type_name)
957
958 if differing is None:
959 if seq1 == seq2:
960 return
961
Serhiy Storchaka77622f52013-09-23 23:07:00 +0300962 differing = '%ss differ: %s != %s\n' % (
963 (seq_type_name.capitalize(),) +
964 _common_shorten_repr(seq1, seq2))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000965
966 for i in range(min(len1, len2)):
967 try:
968 item1 = seq1[i]
969 except (TypeError, IndexError, NotImplementedError):
970 differing += ('\nUnable to index element %d of first %s\n' %
971 (i, seq_type_name))
972 break
973
974 try:
975 item2 = seq2[i]
976 except (TypeError, IndexError, NotImplementedError):
977 differing += ('\nUnable to index element %d of second %s\n' %
978 (i, seq_type_name))
979 break
980
981 if item1 != item2:
982 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
Serhiy Storchaka685fbed2016-04-25 08:58:25 +0300983 ((i,) + _common_shorten_repr(item1, item2)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000984 break
985 else:
986 if (len1 == len2 and seq_type is None and
987 type(seq1) != type(seq2)):
988 # The sequences are the same, but have differing types.
989 return
990
991 if len1 > len2:
992 differing += ('\nFirst %s contains %d additional '
993 'elements.\n' % (seq_type_name, len1 - len2))
994 try:
995 differing += ('First extra element %d:\n%s\n' %
Serhiy Storchaka685fbed2016-04-25 08:58:25 +0300996 (len2, safe_repr(seq1[len2])))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000997 except (TypeError, IndexError, NotImplementedError):
998 differing += ('Unable to index element %d '
999 'of first %s\n' % (len2, seq_type_name))
1000 elif len1 < len2:
1001 differing += ('\nSecond %s contains %d additional '
1002 'elements.\n' % (seq_type_name, len2 - len1))
1003 try:
1004 differing += ('First extra element %d:\n%s\n' %
Serhiy Storchaka685fbed2016-04-25 08:58:25 +03001005 (len1, safe_repr(seq2[len1])))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001006 except (TypeError, IndexError, NotImplementedError):
1007 differing += ('Unable to index element %d '
1008 'of second %s\n' % (len1, seq_type_name))
Michael Foord2034d9a2010-06-05 11:27:52 +00001009 standardMsg = differing
1010 diffMsg = '\n' + '\n'.join(
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001011 difflib.ndiff(pprint.pformat(seq1).splitlines(),
1012 pprint.pformat(seq2).splitlines()))
Michael Foord085dfd32010-06-05 12:17:02 +00001013
1014 standardMsg = self._truncateMessage(standardMsg, diffMsg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001015 msg = self._formatMessage(msg, standardMsg)
1016 self.fail(msg)
1017
Michael Foord085dfd32010-06-05 12:17:02 +00001018 def _truncateMessage(self, message, diff):
1019 max_diff = self.maxDiff
1020 if max_diff is None or len(diff) <= max_diff:
1021 return message + diff
Michael Foord9dad32e2010-06-05 13:49:56 +00001022 return message + (DIFF_OMITTED % len(diff))
Michael Foord085dfd32010-06-05 12:17:02 +00001023
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001024 def assertListEqual(self, list1, list2, msg=None):
1025 """A list-specific equality assertion.
1026
1027 Args:
1028 list1: The first list to compare.
1029 list2: The second list to compare.
1030 msg: Optional message to use on failure instead of a list of
1031 differences.
1032
1033 """
1034 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
1035
1036 def assertTupleEqual(self, tuple1, tuple2, msg=None):
1037 """A tuple-specific equality assertion.
1038
1039 Args:
1040 tuple1: The first tuple to compare.
1041 tuple2: The second tuple to compare.
1042 msg: Optional message to use on failure instead of a list of
1043 differences.
1044 """
1045 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
1046
1047 def assertSetEqual(self, set1, set2, msg=None):
1048 """A set-specific equality assertion.
1049
1050 Args:
1051 set1: The first set to compare.
1052 set2: The second set to compare.
1053 msg: Optional message to use on failure instead of a list of
1054 differences.
1055
Michael Foord91c9da32010-03-20 17:21:27 +00001056 assertSetEqual uses ducktyping to support different types of sets, and
1057 is optimized for sets specifically (parameters must support a
1058 difference method).
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001059 """
1060 try:
1061 difference1 = set1.difference(set2)
1062 except TypeError as e:
1063 self.fail('invalid type when attempting set difference: %s' % e)
1064 except AttributeError as e:
1065 self.fail('first argument does not support set difference: %s' % e)
1066
1067 try:
1068 difference2 = set2.difference(set1)
1069 except TypeError as e:
1070 self.fail('invalid type when attempting set difference: %s' % e)
1071 except AttributeError as e:
1072 self.fail('second argument does not support set difference: %s' % e)
1073
1074 if not (difference1 or difference2):
1075 return
1076
1077 lines = []
1078 if difference1:
1079 lines.append('Items in the first set but not the second:')
1080 for item in difference1:
1081 lines.append(repr(item))
1082 if difference2:
1083 lines.append('Items in the second set but not the first:')
1084 for item in difference2:
1085 lines.append(repr(item))
1086
1087 standardMsg = '\n'.join(lines)
1088 self.fail(self._formatMessage(msg, standardMsg))
1089
1090 def assertIn(self, member, container, msg=None):
1091 """Just like self.assertTrue(a in b), but with a nicer default message."""
1092 if member not in container:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001093 standardMsg = '%s not found in %s' % (safe_repr(member),
1094 safe_repr(container))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001095 self.fail(self._formatMessage(msg, standardMsg))
1096
1097 def assertNotIn(self, member, container, msg=None):
1098 """Just like self.assertTrue(a not in b), but with a nicer default message."""
1099 if member in container:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001100 standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
1101 safe_repr(container))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001102 self.fail(self._formatMessage(msg, standardMsg))
1103
1104 def assertIs(self, expr1, expr2, msg=None):
1105 """Just like self.assertTrue(a is b), but with a nicer default message."""
1106 if expr1 is not expr2:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001107 standardMsg = '%s is not %s' % (safe_repr(expr1),
1108 safe_repr(expr2))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001109 self.fail(self._formatMessage(msg, standardMsg))
1110
1111 def assertIsNot(self, expr1, expr2, msg=None):
1112 """Just like self.assertTrue(a is not b), but with a nicer default message."""
1113 if expr1 is expr2:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001114 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001115 self.fail(self._formatMessage(msg, standardMsg))
1116
1117 def assertDictEqual(self, d1, d2, msg=None):
Ezio Melottib3aedd42010-11-20 19:04:17 +00001118 self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
1119 self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001120
1121 if d1 != d2:
Serhiy Storchaka77622f52013-09-23 23:07:00 +03001122 standardMsg = '%s != %s' % _common_shorten_repr(d1, d2)
Michael Foord085dfd32010-06-05 12:17:02 +00001123 diff = ('\n' + '\n'.join(difflib.ndiff(
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001124 pprint.pformat(d1).splitlines(),
1125 pprint.pformat(d2).splitlines())))
Michael Foordcb11b252010-06-05 13:14:43 +00001126 standardMsg = self._truncateMessage(standardMsg, diff)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001127 self.fail(self._formatMessage(msg, standardMsg))
1128
Ezio Melotti0f535012011-04-03 18:02:13 +03001129 def assertDictContainsSubset(self, subset, dictionary, msg=None):
1130 """Checks whether dictionary is a superset of subset."""
1131 warnings.warn('assertDictContainsSubset is deprecated',
1132 DeprecationWarning)
1133 missing = []
1134 mismatched = []
1135 for key, value in subset.items():
1136 if key not in dictionary:
1137 missing.append(key)
1138 elif value != dictionary[key]:
1139 mismatched.append('%s, expected: %s, actual: %s' %
1140 (safe_repr(key), safe_repr(value),
1141 safe_repr(dictionary[key])))
1142
1143 if not (missing or mismatched):
1144 return
1145
1146 standardMsg = ''
1147 if missing:
1148 standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
1149 missing)
1150 if mismatched:
1151 if standardMsg:
1152 standardMsg += '; '
1153 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
1154
1155 self.fail(self._formatMessage(msg, standardMsg))
1156
1157
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001158 def assertCountEqual(self, first, second, msg=None):
1159 """An unordered sequence comparison asserting that the same elements,
1160 regardless of order. If the same element occurs more than once,
1161 it verifies that the elements occur the same number of times.
Michael Foord8442a602010-03-20 16:58:04 +00001162
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001163 self.assertEqual(Counter(list(first)),
1164 Counter(list(second)))
Michael Foord8442a602010-03-20 16:58:04 +00001165
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001166 Example:
Michael Foord8442a602010-03-20 16:58:04 +00001167 - [0, 1, 1] and [1, 0, 1] compare equal.
1168 - [0, 0, 1] and [0, 1] compare unequal.
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001169
Michael Foord8442a602010-03-20 16:58:04 +00001170 """
Michael Foorde180d392011-01-28 19:51:48 +00001171 first_seq, second_seq = list(first), list(second)
Michael Foord8442a602010-03-20 16:58:04 +00001172 try:
Michael Foorde180d392011-01-28 19:51:48 +00001173 first = collections.Counter(first_seq)
1174 second = collections.Counter(second_seq)
Michael Foord8442a602010-03-20 16:58:04 +00001175 except TypeError:
Raymond Hettinger6518f5e2010-12-24 00:52:54 +00001176 # Handle case with unhashable elements
Michael Foorde180d392011-01-28 19:51:48 +00001177 differences = _count_diff_all_purpose(first_seq, second_seq)
Michael Foord8442a602010-03-20 16:58:04 +00001178 else:
Michael Foorde180d392011-01-28 19:51:48 +00001179 if first == second:
Raymond Hettinger6e165b32010-11-27 09:31:37 +00001180 return
Michael Foorde180d392011-01-28 19:51:48 +00001181 differences = _count_diff_hashable(first_seq, second_seq)
Michael Foord8442a602010-03-20 16:58:04 +00001182
Raymond Hettinger93e233d2010-12-24 10:02:22 +00001183 if differences:
1184 standardMsg = 'Element counts were not equal:\n'
Raymond Hettinger57bd00a2010-12-24 21:51:48 +00001185 lines = ['First has %d, Second has %d: %r' % diff for diff in differences]
Raymond Hettinger93e233d2010-12-24 10:02:22 +00001186 diffMsg = '\n'.join(lines)
1187 standardMsg = self._truncateMessage(standardMsg, diffMsg)
1188 msg = self._formatMessage(msg, standardMsg)
1189 self.fail(msg)
Michael Foord8442a602010-03-20 16:58:04 +00001190
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001191 def assertMultiLineEqual(self, first, second, msg=None):
1192 """Assert that two multi-line strings are equal."""
Ezio Melottib3aedd42010-11-20 19:04:17 +00001193 self.assertIsInstance(first, str, 'First argument is not a string')
1194 self.assertIsInstance(second, str, 'Second argument is not a string')
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001195
1196 if first != second:
Ezio Melottiedd117f2011-04-27 10:20:38 +03001197 # don't use difflib if the strings are too long
1198 if (len(first) > self._diffThreshold or
1199 len(second) > self._diffThreshold):
1200 self._baseAssertEqual(first, second, msg)
Ezio Melottid8b509b2011-09-28 17:37:55 +03001201 firstlines = first.splitlines(keepends=True)
1202 secondlines = second.splitlines(keepends=True)
Michael Foordc653ce32010-07-10 13:52:22 +00001203 if len(firstlines) == 1 and first.strip('\r\n') == first:
1204 firstlines = [first + '\n']
1205 secondlines = [second + '\n']
Serhiy Storchaka77622f52013-09-23 23:07:00 +03001206 standardMsg = '%s != %s' % _common_shorten_repr(first, second)
Michael Foordc653ce32010-07-10 13:52:22 +00001207 diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines))
Michael Foordcb11b252010-06-05 13:14:43 +00001208 standardMsg = self._truncateMessage(standardMsg, diff)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001209 self.fail(self._formatMessage(msg, standardMsg))
1210
1211 def assertLess(self, a, b, msg=None):
1212 """Just like self.assertTrue(a < b), but with a nicer default message."""
1213 if not a < b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001214 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001215 self.fail(self._formatMessage(msg, standardMsg))
1216
1217 def assertLessEqual(self, a, b, msg=None):
1218 """Just like self.assertTrue(a <= b), but with a nicer default message."""
1219 if not a <= b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001220 standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001221 self.fail(self._formatMessage(msg, standardMsg))
1222
1223 def assertGreater(self, a, b, msg=None):
1224 """Just like self.assertTrue(a > b), but with a nicer default message."""
1225 if not a > b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001226 standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001227 self.fail(self._formatMessage(msg, standardMsg))
1228
1229 def assertGreaterEqual(self, a, b, msg=None):
1230 """Just like self.assertTrue(a >= b), but with a nicer default message."""
1231 if not a >= b:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001232 standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001233 self.fail(self._formatMessage(msg, standardMsg))
1234
1235 def assertIsNone(self, obj, msg=None):
1236 """Same as self.assertTrue(obj is None), with a nicer default message."""
1237 if obj is not None:
Benjamin Peterson847a4112010-03-14 15:04:17 +00001238 standardMsg = '%s is not None' % (safe_repr(obj),)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001239 self.fail(self._formatMessage(msg, standardMsg))
1240
1241 def assertIsNotNone(self, obj, msg=None):
1242 """Included for symmetry with assertIsNone."""
1243 if obj is None:
1244 standardMsg = 'unexpectedly None'
1245 self.fail(self._formatMessage(msg, standardMsg))
1246
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001247 def assertIsInstance(self, obj, cls, msg=None):
1248 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
1249 default message."""
1250 if not isinstance(obj, cls):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001251 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001252 self.fail(self._formatMessage(msg, standardMsg))
1253
1254 def assertNotIsInstance(self, obj, cls, msg=None):
1255 """Included for symmetry with assertIsInstance."""
1256 if isinstance(obj, cls):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001257 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001258 self.fail(self._formatMessage(msg, standardMsg))
1259
Ezio Melottied3a7d22010-12-01 02:32:32 +00001260 def assertRaisesRegex(self, expected_exception, expected_regex,
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001261 *args, **kwargs):
Ezio Melottied3a7d22010-12-01 02:32:32 +00001262 """Asserts that the message in a raised exception matches a regex.
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001263
1264 Args:
1265 expected_exception: Exception class expected to be raised.
Ezio Melottied3a7d22010-12-01 02:32:32 +00001266 expected_regex: Regex (re pattern object or string) expected
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001267 to be found in error message.
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001268 args: Function to be called and extra positional args.
1269 kwargs: Extra kwargs.
Ezio Melottib4dc2502011-05-06 15:01:41 +03001270 msg: Optional message used in case of failure. Can only be used
1271 when assertRaisesRegex is used as a context manager.
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001272 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001273 context = _AssertRaisesContext(expected_exception, self, expected_regex)
1274 return context.handle('assertRaisesRegex', args, kwargs)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001275
Ezio Melottied3a7d22010-12-01 02:32:32 +00001276 def assertWarnsRegex(self, expected_warning, expected_regex,
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001277 *args, **kwargs):
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001278 """Asserts that the message in a triggered warning matches a regexp.
1279 Basic functioning is similar to assertWarns() with the addition
1280 that only warnings whose messages also match the regular expression
1281 are considered successful matches.
1282
1283 Args:
1284 expected_warning: Warning class expected to be triggered.
Ezio Melottied3a7d22010-12-01 02:32:32 +00001285 expected_regex: Regex (re pattern object or string) expected
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001286 to be found in error message.
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001287 args: Function to be called and extra positional args.
1288 kwargs: Extra kwargs.
Ezio Melottib4dc2502011-05-06 15:01:41 +03001289 msg: Optional message used in case of failure. Can only be used
1290 when assertWarnsRegex is used as a context manager.
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001291 """
Serhiy Storchakadf573d62015-05-16 16:29:50 +03001292 context = _AssertWarnsContext(expected_warning, self, expected_regex)
1293 return context.handle('assertWarnsRegex', args, kwargs)
Antoine Pitrou4bc12ef2010-09-06 19:25:46 +00001294
Ezio Melottied3a7d22010-12-01 02:32:32 +00001295 def assertRegex(self, text, expected_regex, msg=None):
Michael Foorde3ef5f12010-05-08 16:46:14 +00001296 """Fail the test unless the text matches the regular expression."""
Ezio Melottied3a7d22010-12-01 02:32:32 +00001297 if isinstance(expected_regex, (str, bytes)):
Gregory P. Smithed16bf42010-12-16 19:23:05 +00001298 assert expected_regex, "expected_regex must not be empty."
Ezio Melottied3a7d22010-12-01 02:32:32 +00001299 expected_regex = re.compile(expected_regex)
1300 if not expected_regex.search(text):
Robert Collinsbe6caca2015-08-20 11:13:09 +12001301 standardMsg = "Regex didn't match: %r not found in %r" % (
1302 expected_regex.pattern, text)
1303 # _formatMessage ensures the longMessage option is respected
1304 msg = self._formatMessage(msg, standardMsg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001305 raise self.failureException(msg)
1306
Ezio Melotti8f776302010-12-10 02:32:05 +00001307 def assertNotRegex(self, text, unexpected_regex, msg=None):
Michael Foorde3ef5f12010-05-08 16:46:14 +00001308 """Fail the test if the text matches the regular expression."""
Ezio Melottied3a7d22010-12-01 02:32:32 +00001309 if isinstance(unexpected_regex, (str, bytes)):
1310 unexpected_regex = re.compile(unexpected_regex)
1311 match = unexpected_regex.search(text)
Benjamin Petersonb48af542010-04-11 20:43:16 +00001312 if match:
Robert Collinsbe6caca2015-08-20 11:13:09 +12001313 standardMsg = 'Regex matched: %r matches %r in %r' % (
1314 text[match.start() : match.end()],
1315 unexpected_regex.pattern,
1316 text)
1317 # _formatMessage ensures the longMessage option is respected
1318 msg = self._formatMessage(msg, standardMsg)
Benjamin Petersonb48af542010-04-11 20:43:16 +00001319 raise self.failureException(msg)
1320
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001321
Ezio Melottied3a7d22010-12-01 02:32:32 +00001322 def _deprecate(original_func):
1323 def deprecated_func(*args, **kwargs):
1324 warnings.warn(
1325 'Please use {0} instead.'.format(original_func.__name__),
1326 DeprecationWarning, 2)
1327 return original_func(*args, **kwargs)
1328 return deprecated_func
1329
Ezio Melotti361467e2011-04-03 17:37:58 +03001330 # see #9424
Ezio Melotti0f535012011-04-03 18:02:13 +03001331 failUnlessEqual = assertEquals = _deprecate(assertEqual)
1332 failIfEqual = assertNotEquals = _deprecate(assertNotEqual)
1333 failUnlessAlmostEqual = assertAlmostEquals = _deprecate(assertAlmostEqual)
1334 failIfAlmostEqual = assertNotAlmostEquals = _deprecate(assertNotAlmostEqual)
1335 failUnless = assert_ = _deprecate(assertTrue)
1336 failUnlessRaises = _deprecate(assertRaises)
1337 failIf = _deprecate(assertFalse)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001338 assertRaisesRegexp = _deprecate(assertRaisesRegex)
1339 assertRegexpMatches = _deprecate(assertRegex)
Robert Collinsbe6caca2015-08-20 11:13:09 +12001340 assertNotRegexpMatches = _deprecate(assertNotRegex)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001341
1342
1343
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001344class FunctionTestCase(TestCase):
1345 """A test case that wraps a test function.
1346
1347 This is useful for slipping pre-existing test functions into the
1348 unittest framework. Optionally, set-up and tidy-up functions can be
1349 supplied. As with TestCase, the tidy-up ('tearDown') function will
1350 always be called if the set-up ('setUp') function ran successfully.
1351 """
1352
1353 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
1354 super(FunctionTestCase, self).__init__()
1355 self._setUpFunc = setUp
1356 self._tearDownFunc = tearDown
1357 self._testFunc = testFunc
1358 self._description = description
1359
1360 def setUp(self):
1361 if self._setUpFunc is not None:
1362 self._setUpFunc()
1363
1364 def tearDown(self):
1365 if self._tearDownFunc is not None:
1366 self._tearDownFunc()
1367
1368 def runTest(self):
1369 self._testFunc()
1370
1371 def id(self):
1372 return self._testFunc.__name__
1373
1374 def __eq__(self, other):
1375 if not isinstance(other, self.__class__):
1376 return NotImplemented
1377
1378 return self._setUpFunc == other._setUpFunc and \
1379 self._tearDownFunc == other._tearDownFunc and \
1380 self._testFunc == other._testFunc and \
1381 self._description == other._description
1382
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001383 def __hash__(self):
1384 return hash((type(self), self._setUpFunc, self._tearDownFunc,
1385 self._testFunc, self._description))
1386
1387 def __str__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001388 return "%s (%s)" % (strclass(self.__class__),
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001389 self._testFunc.__name__)
1390
1391 def __repr__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001392 return "<%s tec=%s>" % (strclass(self.__class__),
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001393 self._testFunc)
1394
1395 def shortDescription(self):
1396 if self._description is not None:
1397 return self._description
1398 doc = self._testFunc.__doc__
1399 return doc and doc.split("\n")[0].strip() or None
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +01001400
1401
1402class _SubTest(TestCase):
1403
1404 def __init__(self, test_case, message, params):
1405 super().__init__()
1406 self._message = message
1407 self.test_case = test_case
1408 self.params = params
1409 self.failureException = test_case.failureException
1410
1411 def runTest(self):
1412 raise NotImplementedError("subtests cannot be run directly")
1413
1414 def _subDescription(self):
1415 parts = []
Berker Peksag16ea19f2016-09-21 19:34:15 +03001416 if self._message is not _subtest_msg_sentinel:
Antoine Pitrouc9b3ef22013-03-20 20:16:47 +01001417 parts.append("[{}]".format(self._message))
1418 if self.params:
1419 params_desc = ', '.join(
1420 "{}={!r}".format(k, v)
1421 for (k, v) in sorted(self.params.items()))
1422 parts.append("({})".format(params_desc))
1423 return " ".join(parts) or '(<subtest>)'
1424
1425 def id(self):
1426 return "{} {}".format(self.test_case.id(), self._subDescription())
1427
1428 def shortDescription(self):
1429 """Returns a one-line description of the subtest, or None if no
1430 description has been provided.
1431 """
1432 return self.test_case.shortDescription()
1433
1434 def __str__(self):
1435 return "{} {}".format(self.test_case, self._subDescription())