blob: ac5d1ecc36d0013765d5656fc180ae06a5601da2 [file] [log] [blame]
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001"""Test case implementation"""
2
3import sys
4import functools
5import difflib
6import pprint
7import re
8import warnings
9
Benjamin Peterson847a4112010-03-14 15:04:17 +000010from . import result
11from .util import (strclass, safe_repr, sorted_list_difference,
12 unorderable_list_difference)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000013
Benjamin Petersondccc1fc2010-03-22 00:15:53 +000014__unittest = True
15
Benjamin Petersonbed7d042009-07-19 21:01:52 +000016
17class SkipTest(Exception):
18 """
19 Raise this exception in a test to skip it.
20
21 Usually you can use TestResult.skip() or one of the skipping decorators
22 instead of raising this directly.
23 """
24 pass
25
26class _ExpectedFailure(Exception):
27 """
28 Raise this when a test is expected to fail.
29
30 This is an implementation detail.
31 """
32
33 def __init__(self, exc_info):
34 super(_ExpectedFailure, self).__init__()
35 self.exc_info = exc_info
36
37class _UnexpectedSuccess(Exception):
38 """
39 The test was supposed to fail, but it didn't!
40 """
41 pass
42
43def _id(obj):
44 return obj
45
46def skip(reason):
47 """
48 Unconditionally skip a test.
49 """
50 def decorator(test_item):
Benjamin Peterson847a4112010-03-14 15:04:17 +000051 if not (isinstance(test_item, type) and issubclass(test_item, TestCase)):
52 @functools.wraps(test_item)
53 def skip_wrapper(*args, **kwargs):
54 raise SkipTest(reason)
55 test_item = skip_wrapper
56
57 test_item.__unittest_skip__ = True
58 test_item.__unittest_skip_why__ = reason
59 return test_item
Benjamin Petersonbed7d042009-07-19 21:01:52 +000060 return decorator
61
62def skipIf(condition, reason):
63 """
64 Skip a test if the condition is true.
65 """
66 if condition:
67 return skip(reason)
68 return _id
69
70def skipUnless(condition, reason):
71 """
72 Skip a test unless the condition is true.
73 """
74 if not condition:
75 return skip(reason)
76 return _id
77
78
79def expectedFailure(func):
80 @functools.wraps(func)
81 def wrapper(*args, **kwargs):
82 try:
83 func(*args, **kwargs)
84 except Exception:
85 raise _ExpectedFailure(sys.exc_info())
86 raise _UnexpectedSuccess
87 return wrapper
88
89
90class _AssertRaisesContext(object):
91 """A context manager used to implement TestCase.assertRaises* methods."""
92
93 def __init__(self, expected, test_case, callable_obj=None,
94 expected_regexp=None):
95 self.expected = expected
96 self.failureException = test_case.failureException
97 if callable_obj is not None:
98 try:
99 self.obj_name = callable_obj.__name__
100 except AttributeError:
101 self.obj_name = str(callable_obj)
102 else:
103 self.obj_name = None
Georg Brandl89fad142010-03-14 10:23:39 +0000104 self.expected_regexp = expected_regexp
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000105
106 def __enter__(self):
Ezio Melotti49008232010-02-08 21:57:48 +0000107 return self
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000108
109 def __exit__(self, exc_type, exc_value, tb):
110 if exc_type is None:
111 try:
112 exc_name = self.expected.__name__
113 except AttributeError:
114 exc_name = str(self.expected)
115 if self.obj_name:
116 raise self.failureException("{0} not raised by {1}"
117 .format(exc_name, self.obj_name))
118 else:
119 raise self.failureException("{0} not raised"
120 .format(exc_name))
121 if not issubclass(exc_type, self.expected):
122 # let unexpected exceptions pass through
123 return False
Ezio Melotti49008232010-02-08 21:57:48 +0000124 # store exception, without traceback, for later retrieval
125 self.exception = exc_value.with_traceback(None)
Georg Brandl89fad142010-03-14 10:23:39 +0000126 if self.expected_regexp is None:
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000127 return True
128
Georg Brandl89fad142010-03-14 10:23:39 +0000129 expected_regexp = self.expected_regexp
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000130 if isinstance(expected_regexp, (bytes, str)):
131 expected_regexp = re.compile(expected_regexp)
132 if not expected_regexp.search(str(exc_value)):
133 raise self.failureException('"%s" does not match "%s"' %
134 (expected_regexp.pattern, str(exc_value)))
135 return True
136
137
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000138class TestCase(object):
139 """A class whose instances are single test cases.
140
141 By default, the test code itself should be placed in a method named
142 'runTest'.
143
144 If the fixture may be used for many test cases, create as
145 many test methods as are needed. When instantiating such a TestCase
146 subclass, specify in the constructor arguments the name of the test method
147 that the instance is to execute.
148
149 Test authors should subclass TestCase for their own tests. Construction
150 and deconstruction of the test's environment ('fixture') can be
151 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
152
153 If it is necessary to override the __init__ method, the base class
154 __init__ method must always be called. It is important that subclasses
155 should not change the signature of their __init__ method, since instances
156 of the classes are instantiated automatically by parts of the framework
157 in order to be run.
158 """
159
160 # This attribute determines which exception will be raised when
161 # the instance's assertion methods fail; test methods raising this
162 # exception will be deemed to have 'failed' rather than 'errored'
163
164 failureException = AssertionError
165
166 # This attribute determines whether long messages (including repr of
167 # objects used in assert methods) will be printed on failure in *addition*
168 # to any explicit message passed.
169
170 longMessage = False
171
Benjamin Peterson847a4112010-03-14 15:04:17 +0000172 # Attribute used by TestSuite for classSetUp
173
174 _classSetupFailed = False
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000175
176 def __init__(self, methodName='runTest'):
177 """Create an instance of the class that will use the named test
178 method when executed. Raises a ValueError if the instance does
179 not have a method with the specified name.
180 """
181 self._testMethodName = methodName
182 self._resultForDoCleanups = None
183 try:
184 testMethod = getattr(self, methodName)
185 except AttributeError:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000186 raise ValueError("no such test method in %s: %s" %
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000187 (self.__class__, methodName))
188 self._testMethodDoc = testMethod.__doc__
189 self._cleanups = []
190
191 # Map types to custom assertEqual functions that will compare
192 # instances of said type in more detail to generate a more useful
193 # error message.
194 self._type_equality_funcs = {}
195 self.addTypeEqualityFunc(dict, self.assertDictEqual)
196 self.addTypeEqualityFunc(list, self.assertListEqual)
197 self.addTypeEqualityFunc(tuple, self.assertTupleEqual)
198 self.addTypeEqualityFunc(set, self.assertSetEqual)
199 self.addTypeEqualityFunc(frozenset, self.assertSetEqual)
Michael Foord02834952010-02-08 23:10:39 +0000200 self.addTypeEqualityFunc(str, self.assertMultiLineEqual)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000201
202 def addTypeEqualityFunc(self, typeobj, function):
203 """Add a type specific assertEqual style function to compare a type.
204
205 This method is for use by TestCase subclasses that need to register
206 their own type equality functions to provide nicer error messages.
207
208 Args:
209 typeobj: The data type to call this function on when both values
210 are of the same type in assertEqual().
211 function: The callable taking two arguments and an optional
212 msg= argument that raises self.failureException with a
213 useful error message when the two arguments are not equal.
214 """
Benjamin Peterson8f326b22009-12-13 02:10:36 +0000215 self._type_equality_funcs[typeobj] = function
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000216
217 def addCleanup(self, function, *args, **kwargs):
218 """Add a function, with arguments, to be called when the test is
219 completed. Functions added are called on a LIFO basis and are
220 called after tearDown on test failure or success.
221
222 Cleanup items are called even if setUp fails (unlike tearDown)."""
223 self._cleanups.append((function, args, kwargs))
224
225 def setUp(self):
226 "Hook method for setting up the test fixture before exercising it."
227 pass
228
229 def tearDown(self):
230 "Hook method for deconstructing the test fixture after testing it."
231 pass
232
Benjamin Peterson847a4112010-03-14 15:04:17 +0000233 @classmethod
234 def setUpClass(cls):
235 "Hook method for setting up class fixture before running tests in the class."
236
237 @classmethod
238 def tearDownClass(cls):
239 "Hook method for deconstructing the class fixture after running all tests in the class."
240
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000241 def countTestCases(self):
242 return 1
243
244 def defaultTestResult(self):
245 return result.TestResult()
246
247 def shortDescription(self):
Michael Foord34c94622010-02-10 15:51:42 +0000248 """Returns a one-line description of the test, or None if no
249 description has been provided.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000250
Michael Foord34c94622010-02-10 15:51:42 +0000251 The default implementation of this method returns the first line of
252 the specified test method's docstring.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000253 """
Michael Foord34c94622010-02-10 15:51:42 +0000254 doc = self._testMethodDoc
255 return doc and doc.split("\n")[0].strip() or None
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000256
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000257
258 def id(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000259 return "%s.%s" % (strclass(self.__class__), self._testMethodName)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000260
261 def __eq__(self, other):
262 if type(self) is not type(other):
263 return NotImplemented
264
265 return self._testMethodName == other._testMethodName
266
267 def __ne__(self, other):
268 return not self == other
269
270 def __hash__(self):
271 return hash((type(self), self._testMethodName))
272
273 def __str__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000274 return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000275
276 def __repr__(self):
277 return "<%s testMethod=%s>" % \
Benjamin Peterson847a4112010-03-14 15:04:17 +0000278 (strclass(self.__class__), self._testMethodName)
279
280 def _addSkip(self, result, reason):
281 addSkip = getattr(result, 'addSkip', None)
282 if addSkip is not None:
283 addSkip(self, reason)
284 else:
285 warnings.warn("TestResult has no addSkip method, skips not reported",
286 RuntimeWarning, 2)
287 result.addSuccess(self)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000288
289 def run(self, result=None):
290 orig_result = result
291 if result is None:
292 result = self.defaultTestResult()
293 startTestRun = getattr(result, 'startTestRun', None)
294 if startTestRun is not None:
295 startTestRun()
296
297 self._resultForDoCleanups = result
298 result.startTest(self)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000299
300 testMethod = getattr(self, self._testMethodName)
301 if (getattr(self.__class__, "__unittest_skip__", False) or
302 getattr(testMethod, "__unittest_skip__", False)):
303 # If the class or method was skipped.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000304 try:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000305 skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
306 or getattr(testMethod, '__unittest_skip_why__', ''))
307 self._addSkip(result, skip_why)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000308 finally:
309 result.stopTest(self)
310 return
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000311 try:
312 success = False
313 try:
314 self.setUp()
315 except SkipTest as e:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000316 self._addSkip(result, str(e))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000317 except Exception:
318 result.addError(self, sys.exc_info())
319 else:
320 try:
321 testMethod()
322 except self.failureException:
323 result.addFailure(self, sys.exc_info())
324 except _ExpectedFailure as e:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000325 addExpectedFailure = getattr(result, 'addExpectedFailure', None)
326 if addExpectedFailure is not None:
327 addExpectedFailure(self, e.exc_info)
328 else:
329 warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
330 RuntimeWarning)
331 result.addSuccess(self)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000332 except _UnexpectedSuccess:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000333 addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
334 if addUnexpectedSuccess is not None:
335 addUnexpectedSuccess(self)
336 else:
337 warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures",
338 RuntimeWarning)
339 result.addFailure(self, sys.exc_info())
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000340 except SkipTest as e:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000341 self._addSkip(result, str(e))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000342 except Exception:
343 result.addError(self, sys.exc_info())
344 else:
345 success = True
346
347 try:
348 self.tearDown()
349 except Exception:
350 result.addError(self, sys.exc_info())
351 success = False
352
353 cleanUpSuccess = self.doCleanups()
354 success = success and cleanUpSuccess
355 if success:
356 result.addSuccess(self)
357 finally:
358 result.stopTest(self)
359 if orig_result is None:
360 stopTestRun = getattr(result, 'stopTestRun', None)
361 if stopTestRun is not None:
362 stopTestRun()
363
364 def doCleanups(self):
365 """Execute all cleanup functions. Normally called for you after
366 tearDown."""
367 result = self._resultForDoCleanups
368 ok = True
369 while self._cleanups:
370 function, args, kwargs = self._cleanups.pop(-1)
371 try:
372 function(*args, **kwargs)
373 except Exception:
374 ok = False
375 result.addError(self, sys.exc_info())
376 return ok
377
378 def __call__(self, *args, **kwds):
379 return self.run(*args, **kwds)
380
381 def debug(self):
382 """Run the test without collecting errors in a TestResult"""
383 self.setUp()
384 getattr(self, self._testMethodName)()
385 self.tearDown()
386
387 def skipTest(self, reason):
388 """Skip this test."""
389 raise SkipTest(reason)
390
391 def fail(self, msg=None):
392 """Fail immediately, with the given message."""
393 raise self.failureException(msg)
394
395 def assertFalse(self, expr, msg=None):
396 "Fail the test if the expression is true."
397 if expr:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000398 msg = self._formatMessage(msg, "%s is not False" % safe_repr(expr))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000399 raise self.failureException(msg)
400
401 def assertTrue(self, expr, msg=None):
402 """Fail the test unless the expression is true."""
403 if not expr:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000404 msg = self._formatMessage(msg, "%s is not True" % safe_repr(expr))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000405 raise self.failureException(msg)
406
407 def _formatMessage(self, msg, standardMsg):
408 """Honour the longMessage attribute when generating failure messages.
409 If longMessage is False this means:
410 * Use only an explicit message if it is provided
411 * Otherwise use the standard message for the assert
412
413 If longMessage is True:
414 * Use the standard message
415 * If an explicit message is provided, plus ' : ' and the explicit message
416 """
417 if not self.longMessage:
418 return msg or standardMsg
419 if msg is None:
420 return standardMsg
Benjamin Peterson847a4112010-03-14 15:04:17 +0000421 try:
422 # don't switch to '{}' formatting in Python 2.X
423 # it changes the way unicode input is handled
424 return '%s : %s' % (standardMsg, msg)
425 except UnicodeDecodeError:
426 return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000427
428
429 def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
430 """Fail unless an exception of class excClass is thrown
431 by callableObj when invoked with arguments args and keyword
432 arguments kwargs. If a different type of exception is
433 thrown, it will not be caught, and the test case will be
434 deemed to have suffered an error, exactly as for an
435 unexpected exception.
436
437 If called with callableObj omitted or None, will return a
438 context object used like this::
439
Michael Foord1c42b122010-02-05 22:58:21 +0000440 with self.assertRaises(SomeException):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000441 do_something()
Michael Foord1c42b122010-02-05 22:58:21 +0000442
443 The context manager keeps a reference to the exception as
Ezio Melotti49008232010-02-08 21:57:48 +0000444 the 'exception' attribute. This allows you to inspect the
Michael Foord1c42b122010-02-05 22:58:21 +0000445 exception after the assertion::
446
447 with self.assertRaises(SomeException) as cm:
448 do_something()
Ezio Melotti49008232010-02-08 21:57:48 +0000449 the_exception = cm.exception
Michael Foordb57ac6d2010-02-05 23:26:29 +0000450 self.assertEqual(the_exception.error_code, 3)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000451 """
452 context = _AssertRaisesContext(excClass, self, callableObj)
453 if callableObj is None:
454 return context
455 with context:
456 callableObj(*args, **kwargs)
457
458 def _getAssertEqualityFunc(self, first, second):
459 """Get a detailed comparison function for the types of the two args.
460
461 Returns: A callable accepting (first, second, msg=None) that will
462 raise a failure exception if first != second with a useful human
463 readable error message for those types.
464 """
465 #
466 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
467 # and vice versa. I opted for the conservative approach in case
468 # subclasses are not intended to be compared in detail to their super
469 # class instances using a type equality func. This means testing
470 # subtypes won't automagically use the detailed comparison. Callers
471 # should use their type specific assertSpamEqual method to compare
472 # subclasses if the detailed comparison is desired and appropriate.
473 # See the discussion in http://bugs.python.org/issue2578.
474 #
475 if type(first) is type(second):
476 asserter = self._type_equality_funcs.get(type(first))
477 if asserter is not None:
Benjamin Peterson8f326b22009-12-13 02:10:36 +0000478 return asserter
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000479
480 return self._baseAssertEqual
481
482 def _baseAssertEqual(self, first, second, msg=None):
483 """The default assertEqual implementation, not type specific."""
484 if not first == second:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000485 standardMsg = '%s != %s' % (safe_repr(first), safe_repr(second))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000486 msg = self._formatMessage(msg, standardMsg)
487 raise self.failureException(msg)
488
489 def assertEqual(self, first, second, msg=None):
490 """Fail if the two objects are unequal as determined by the '=='
491 operator.
492 """
493 assertion_func = self._getAssertEqualityFunc(first, second)
494 assertion_func(first, second, msg=msg)
495
496 def assertNotEqual(self, first, second, msg=None):
497 """Fail if the two objects are equal as determined by the '=='
498 operator.
499 """
500 if not first != second:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000501 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
502 safe_repr(second)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000503 raise self.failureException(msg)
504
505 def assertAlmostEqual(self, first, second, *, places=7, msg=None):
506 """Fail if the two objects are unequal as determined by their
507 difference rounded to the given number of decimal places
508 (default 7) and comparing to zero.
509
510 Note that decimal places (from zero) are usually not the same
511 as significant digits (measured from the most signficant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000512
513 If the two objects compare equal then they will automatically
514 compare almost equal.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000515 """
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000516 if first == second:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000517 # shortcut for inf
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000518 return
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000519 if round(abs(second-first), places) != 0:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000520 standardMsg = '%s != %s within %r places' % (safe_repr(first),
521 safe_repr(second),
522 places)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000523 msg = self._formatMessage(msg, standardMsg)
524 raise self.failureException(msg)
525
526 def assertNotAlmostEqual(self, first, second, *, places=7, msg=None):
527 """Fail if the two objects are equal as determined by their
528 difference rounded to the given number of decimal places
529 (default 7) and comparing to zero.
530
531 Note that decimal places (from zero) are usually not the same
532 as significant digits (measured from the most signficant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000533
534 Objects that are equal automatically fail.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000535 """
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000536 if (first == second) or round(abs(second-first), places) == 0:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000537 standardMsg = '%s == %s within %r places' % (safe_repr(first),
538 safe_repr(second),
539 places)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000540 msg = self._formatMessage(msg, standardMsg)
541 raise self.failureException(msg)
542
543 # Synonyms for assertion methods
544
545 # The plurals are undocumented. Keep them that way to discourage use.
546 # Do not add more. Do not remove.
547 # Going through a deprecation cycle on these would annoy many people.
548 assertEquals = assertEqual
549 assertNotEquals = assertNotEqual
550 assertAlmostEquals = assertAlmostEqual
551 assertNotAlmostEquals = assertNotAlmostEqual
Michael Foord0e31b992010-02-10 15:52:56 +0000552 assert_ = assertTrue
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000553
554 # These fail* assertion method names are pending deprecation and will
555 # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
556 def _deprecate(original_func):
557 def deprecated_func(*args, **kwargs):
558 warnings.warn(
559 'Please use {0} instead.'.format(original_func.__name__),
560 DeprecationWarning, 2)
561 return original_func(*args, **kwargs)
562 return deprecated_func
563
564 failUnlessEqual = _deprecate(assertEqual)
565 failIfEqual = _deprecate(assertNotEqual)
566 failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
567 failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
568 failUnless = _deprecate(assertTrue)
569 failUnlessRaises = _deprecate(assertRaises)
570 failIf = _deprecate(assertFalse)
571
572 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
573 """An equality assertion for ordered sequences (like lists and tuples).
574
R. David Murrayad13f222010-01-29 22:17:58 +0000575 For the purposes of this function, a valid ordered sequence type is one
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000576 which can be indexed, has a length, and has an equality operator.
577
578 Args:
579 seq1: The first sequence to compare.
580 seq2: The second sequence to compare.
581 seq_type: The expected datatype of the sequences, or None if no
582 datatype should be enforced.
583 msg: Optional message to use on failure instead of a list of
584 differences.
585 """
586 if seq_type != None:
587 seq_type_name = seq_type.__name__
588 if not isinstance(seq1, seq_type):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000589 raise self.failureException('First sequence is not a %s: %s'
590 % (seq_type_name, safe_repr(seq1)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000591 if not isinstance(seq2, seq_type):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000592 raise self.failureException('Second sequence is not a %s: %s'
593 % (seq_type_name, safe_repr(seq2)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000594 else:
595 seq_type_name = "sequence"
596
597 differing = None
598 try:
599 len1 = len(seq1)
600 except (TypeError, NotImplementedError):
601 differing = 'First %s has no length. Non-sequence?' % (
602 seq_type_name)
603
604 if differing is None:
605 try:
606 len2 = len(seq2)
607 except (TypeError, NotImplementedError):
608 differing = 'Second %s has no length. Non-sequence?' % (
609 seq_type_name)
610
611 if differing is None:
612 if seq1 == seq2:
613 return
614
Benjamin Peterson847a4112010-03-14 15:04:17 +0000615 seq1_repr = safe_repr(seq1)
616 seq2_repr = safe_repr(seq2)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000617 if len(seq1_repr) > 30:
618 seq1_repr = seq1_repr[:30] + '...'
619 if len(seq2_repr) > 30:
620 seq2_repr = seq2_repr[:30] + '...'
621 elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
622 differing = '%ss differ: %s != %s\n' % elements
623
624 for i in range(min(len1, len2)):
625 try:
626 item1 = seq1[i]
627 except (TypeError, IndexError, NotImplementedError):
628 differing += ('\nUnable to index element %d of first %s\n' %
629 (i, seq_type_name))
630 break
631
632 try:
633 item2 = seq2[i]
634 except (TypeError, IndexError, NotImplementedError):
635 differing += ('\nUnable to index element %d of second %s\n' %
636 (i, seq_type_name))
637 break
638
639 if item1 != item2:
640 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
641 (i, item1, item2))
642 break
643 else:
644 if (len1 == len2 and seq_type is None and
645 type(seq1) != type(seq2)):
646 # The sequences are the same, but have differing types.
647 return
648
649 if len1 > len2:
650 differing += ('\nFirst %s contains %d additional '
651 'elements.\n' % (seq_type_name, len1 - len2))
652 try:
653 differing += ('First extra element %d:\n%s\n' %
654 (len2, seq1[len2]))
655 except (TypeError, IndexError, NotImplementedError):
656 differing += ('Unable to index element %d '
657 'of first %s\n' % (len2, seq_type_name))
658 elif len1 < len2:
659 differing += ('\nSecond %s contains %d additional '
660 'elements.\n' % (seq_type_name, len2 - len1))
661 try:
662 differing += ('First extra element %d:\n%s\n' %
663 (len1, seq2[len1]))
664 except (TypeError, IndexError, NotImplementedError):
665 differing += ('Unable to index element %d '
666 'of second %s\n' % (len1, seq_type_name))
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000667 standardMsg = differing + '\n' + '\n'.join(
668 difflib.ndiff(pprint.pformat(seq1).splitlines(),
669 pprint.pformat(seq2).splitlines()))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000670 msg = self._formatMessage(msg, standardMsg)
671 self.fail(msg)
672
673 def assertListEqual(self, list1, list2, msg=None):
674 """A list-specific equality assertion.
675
676 Args:
677 list1: The first list to compare.
678 list2: The second list to compare.
679 msg: Optional message to use on failure instead of a list of
680 differences.
681
682 """
683 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
684
685 def assertTupleEqual(self, tuple1, tuple2, msg=None):
686 """A tuple-specific equality assertion.
687
688 Args:
689 tuple1: The first tuple to compare.
690 tuple2: The second tuple to compare.
691 msg: Optional message to use on failure instead of a list of
692 differences.
693 """
694 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
695
696 def assertSetEqual(self, set1, set2, msg=None):
697 """A set-specific equality assertion.
698
699 Args:
700 set1: The first set to compare.
701 set2: The second set to compare.
702 msg: Optional message to use on failure instead of a list of
703 differences.
704
Michael Foord91c9da32010-03-20 17:21:27 +0000705 assertSetEqual uses ducktyping to support different types of sets, and
706 is optimized for sets specifically (parameters must support a
707 difference method).
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000708 """
709 try:
710 difference1 = set1.difference(set2)
711 except TypeError as e:
712 self.fail('invalid type when attempting set difference: %s' % e)
713 except AttributeError as e:
714 self.fail('first argument does not support set difference: %s' % e)
715
716 try:
717 difference2 = set2.difference(set1)
718 except TypeError as e:
719 self.fail('invalid type when attempting set difference: %s' % e)
720 except AttributeError as e:
721 self.fail('second argument does not support set difference: %s' % e)
722
723 if not (difference1 or difference2):
724 return
725
726 lines = []
727 if difference1:
728 lines.append('Items in the first set but not the second:')
729 for item in difference1:
730 lines.append(repr(item))
731 if difference2:
732 lines.append('Items in the second set but not the first:')
733 for item in difference2:
734 lines.append(repr(item))
735
736 standardMsg = '\n'.join(lines)
737 self.fail(self._formatMessage(msg, standardMsg))
738
739 def assertIn(self, member, container, msg=None):
740 """Just like self.assertTrue(a in b), but with a nicer default message."""
741 if member not in container:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000742 standardMsg = '%s not found in %s' % (safe_repr(member),
743 safe_repr(container))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000744 self.fail(self._formatMessage(msg, standardMsg))
745
746 def assertNotIn(self, member, container, msg=None):
747 """Just like self.assertTrue(a not in b), but with a nicer default message."""
748 if member in container:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000749 standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
750 safe_repr(container))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000751 self.fail(self._formatMessage(msg, standardMsg))
752
753 def assertIs(self, expr1, expr2, msg=None):
754 """Just like self.assertTrue(a is b), but with a nicer default message."""
755 if expr1 is not expr2:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000756 standardMsg = '%s is not %s' % (safe_repr(expr1),
757 safe_repr(expr2))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000758 self.fail(self._formatMessage(msg, standardMsg))
759
760 def assertIsNot(self, expr1, expr2, msg=None):
761 """Just like self.assertTrue(a is not b), but with a nicer default message."""
762 if expr1 is expr2:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000763 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000764 self.fail(self._formatMessage(msg, standardMsg))
765
766 def assertDictEqual(self, d1, d2, msg=None):
767 self.assert_(isinstance(d1, dict), 'First argument is not a dictionary')
768 self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary')
769
770 if d1 != d2:
771 standardMsg = ('\n' + '\n'.join(difflib.ndiff(
772 pprint.pformat(d1).splitlines(),
773 pprint.pformat(d2).splitlines())))
774 self.fail(self._formatMessage(msg, standardMsg))
775
776 def assertDictContainsSubset(self, expected, actual, msg=None):
777 """Checks whether actual is a superset of expected."""
778 missing = []
779 mismatched = []
780 for key, value in expected.items():
781 if key not in actual:
782 missing.append(key)
783 elif value != actual[key]:
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000784 mismatched.append('%s, expected: %s, actual: %s' %
Benjamin Peterson847a4112010-03-14 15:04:17 +0000785 (safe_repr(key), safe_repr(value),
786 safe_repr(actual[key])))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000787
788 if not (missing or mismatched):
789 return
790
791 standardMsg = ''
792 if missing:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000793 standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
794 missing)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000795 if mismatched:
796 if standardMsg:
797 standardMsg += '; '
798 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
799
800 self.fail(self._formatMessage(msg, standardMsg))
801
802 def assertSameElements(self, expected_seq, actual_seq, msg=None):
803 """An unordered sequence specific comparison.
804
805 Raises with an error message listing which elements of expected_seq
806 are missing from actual_seq and vice versa if any.
Michael Foord1c42b122010-02-05 22:58:21 +0000807
808 Duplicate elements are ignored when comparing *expected_seq* and
809 *actual_seq*. It is the equivalent of ``assertEqual(set(expected),
810 set(actual))`` but it works with sequences of unhashable objects as
811 well.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000812 """
Michael Foord91c9da32010-03-20 17:21:27 +0000813 warnings.warn('assertSameElements is deprecated',
814 DeprecationWarning)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000815 try:
816 expected = set(expected_seq)
817 actual = set(actual_seq)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000818 missing = sorted(expected.difference(actual))
819 unexpected = sorted(actual.difference(expected))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000820 except TypeError:
821 # Fall back to slower list-compare if any of the objects are
822 # not hashable.
823 expected = list(expected_seq)
824 actual = list(actual_seq)
825 try:
826 expected.sort()
827 actual.sort()
828 except TypeError:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000829 missing, unexpected = unorderable_list_difference(expected,
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000830 actual)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000831 else:
832 missing, unexpected = sorted_list_difference(expected, actual)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000833 errors = []
834 if missing:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000835 errors.append('Expected, but missing:\n %s' %
836 safe_repr(missing))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000837 if unexpected:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000838 errors.append('Unexpected, but present:\n %s' %
839 safe_repr(unexpected))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000840 if errors:
841 standardMsg = '\n'.join(errors)
842 self.fail(self._formatMessage(msg, standardMsg))
843
Michael Foord8442a602010-03-20 16:58:04 +0000844
845 def assertItemsEqual(self, expected_seq, actual_seq, msg=None):
846 """An unordered sequence / set specific comparison. It asserts that
847 expected_seq and actual_seq contain the same elements. It is
848 the equivalent of::
849
850 self.assertEqual(sorted(expected_seq), sorted(actual_seq))
851
852 Raises with an error message listing which elements of expected_seq
853 are missing from actual_seq and vice versa if any.
854
855 Asserts that each element has the same count in both sequences.
856 Example:
857 - [0, 1, 1] and [1, 0, 1] compare equal.
858 - [0, 0, 1] and [0, 1] compare unequal.
859 """
860 try:
861 expected = sorted(expected_seq)
862 actual = sorted(actual_seq)
863 except TypeError:
864 # Unsortable items (example: set(), complex(), ...)
865 expected = list(expected_seq)
866 actual = list(actual_seq)
867 missing, unexpected = unorderable_list_difference(expected, actual)
868 else:
869 return self.assertSequenceEqual(expected, actual, msg=msg)
870
871 errors = []
872 if missing:
873 errors.append('Expected, but missing:\n %s' %
874 safe_repr(missing))
875 if unexpected:
876 errors.append('Unexpected, but present:\n %s' %
877 safe_repr(unexpected))
878 if errors:
879 standardMsg = '\n'.join(errors)
880 self.fail(self._formatMessage(msg, standardMsg))
881
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000882 def assertMultiLineEqual(self, first, second, msg=None):
883 """Assert that two multi-line strings are equal."""
884 self.assert_(isinstance(first, str), (
885 'First argument is not a string'))
886 self.assert_(isinstance(second, str), (
887 'Second argument is not a string'))
888
889 if first != second:
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000890 standardMsg = '\n' + ''.join(difflib.ndiff(first.splitlines(True),
891 second.splitlines(True)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000892 self.fail(self._formatMessage(msg, standardMsg))
893
894 def assertLess(self, a, b, msg=None):
895 """Just like self.assertTrue(a < b), but with a nicer default message."""
896 if not a < b:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000897 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000898 self.fail(self._formatMessage(msg, standardMsg))
899
900 def assertLessEqual(self, a, b, msg=None):
901 """Just like self.assertTrue(a <= b), but with a nicer default message."""
902 if not a <= b:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000903 standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000904 self.fail(self._formatMessage(msg, standardMsg))
905
906 def assertGreater(self, a, b, msg=None):
907 """Just like self.assertTrue(a > b), but with a nicer default message."""
908 if not a > b:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000909 standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000910 self.fail(self._formatMessage(msg, standardMsg))
911
912 def assertGreaterEqual(self, a, b, msg=None):
913 """Just like self.assertTrue(a >= b), but with a nicer default message."""
914 if not a >= b:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000915 standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000916 self.fail(self._formatMessage(msg, standardMsg))
917
918 def assertIsNone(self, obj, msg=None):
919 """Same as self.assertTrue(obj is None), with a nicer default message."""
920 if obj is not None:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000921 standardMsg = '%s is not None' % (safe_repr(obj),)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000922 self.fail(self._formatMessage(msg, standardMsg))
923
924 def assertIsNotNone(self, obj, msg=None):
925 """Included for symmetry with assertIsNone."""
926 if obj is None:
927 standardMsg = 'unexpectedly None'
928 self.fail(self._formatMessage(msg, standardMsg))
929
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000930 def assertIsInstance(self, obj, cls, msg=None):
931 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
932 default message."""
933 if not isinstance(obj, cls):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000934 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000935 self.fail(self._formatMessage(msg, standardMsg))
936
937 def assertNotIsInstance(self, obj, cls, msg=None):
938 """Included for symmetry with assertIsInstance."""
939 if isinstance(obj, cls):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000940 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000941 self.fail(self._formatMessage(msg, standardMsg))
942
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000943 def assertRaisesRegexp(self, expected_exception, expected_regexp,
944 callable_obj=None, *args, **kwargs):
945 """Asserts that the message in a raised exception matches a regexp.
946
947 Args:
948 expected_exception: Exception class expected to be raised.
949 expected_regexp: Regexp (re pattern object or string) expected
950 to be found in error message.
951 callable_obj: Function to be called.
952 args: Extra args.
953 kwargs: Extra kwargs.
954 """
955 context = _AssertRaisesContext(expected_exception, self, callable_obj,
956 expected_regexp)
957 if callable_obj is None:
958 return context
959 with context:
960 callable_obj(*args, **kwargs)
961
Georg Brandl89fad142010-03-14 10:23:39 +0000962 def assertRegexpMatches(self, text, expected_regexp, msg=None):
963 if isinstance(expected_regexp, (str, bytes)):
964 expected_regexp = re.compile(expected_regexp)
965 if not expected_regexp.search(text):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000966 msg = msg or "Regexp didn't match"
Georg Brandl89fad142010-03-14 10:23:39 +0000967 msg = '%s: %r not found in %r' % (msg, expected_regexp.pattern, text)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000968 raise self.failureException(msg)
969
970
971class FunctionTestCase(TestCase):
972 """A test case that wraps a test function.
973
974 This is useful for slipping pre-existing test functions into the
975 unittest framework. Optionally, set-up and tidy-up functions can be
976 supplied. As with TestCase, the tidy-up ('tearDown') function will
977 always be called if the set-up ('setUp') function ran successfully.
978 """
979
980 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
981 super(FunctionTestCase, self).__init__()
982 self._setUpFunc = setUp
983 self._tearDownFunc = tearDown
984 self._testFunc = testFunc
985 self._description = description
986
987 def setUp(self):
988 if self._setUpFunc is not None:
989 self._setUpFunc()
990
991 def tearDown(self):
992 if self._tearDownFunc is not None:
993 self._tearDownFunc()
994
995 def runTest(self):
996 self._testFunc()
997
998 def id(self):
999 return self._testFunc.__name__
1000
1001 def __eq__(self, other):
1002 if not isinstance(other, self.__class__):
1003 return NotImplemented
1004
1005 return self._setUpFunc == other._setUpFunc and \
1006 self._tearDownFunc == other._tearDownFunc and \
1007 self._testFunc == other._testFunc and \
1008 self._description == other._description
1009
1010 def __ne__(self, other):
1011 return not self == other
1012
1013 def __hash__(self):
1014 return hash((type(self), self._setUpFunc, self._tearDownFunc,
1015 self._testFunc, self._description))
1016
1017 def __str__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001018 return "%s (%s)" % (strclass(self.__class__),
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001019 self._testFunc.__name__)
1020
1021 def __repr__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001022 return "<%s tec=%s>" % (strclass(self.__class__),
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001023 self._testFunc)
1024
1025 def shortDescription(self):
1026 if self._description is not None:
1027 return self._description
1028 doc = self._testFunc.__doc__
1029 return doc and doc.split("\n")[0].strip() or None