blob: 88254be68b4e0538c7f37586d8c18e2832f3248a [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
10from . import result, util
11
12
13class SkipTest(Exception):
14 """
15 Raise this exception in a test to skip it.
16
17 Usually you can use TestResult.skip() or one of the skipping decorators
18 instead of raising this directly.
19 """
20 pass
21
22class _ExpectedFailure(Exception):
23 """
24 Raise this when a test is expected to fail.
25
26 This is an implementation detail.
27 """
28
29 def __init__(self, exc_info):
30 super(_ExpectedFailure, self).__init__()
31 self.exc_info = exc_info
32
33class _UnexpectedSuccess(Exception):
34 """
35 The test was supposed to fail, but it didn't!
36 """
37 pass
38
39def _id(obj):
40 return obj
41
42def skip(reason):
43 """
44 Unconditionally skip a test.
45 """
46 def decorator(test_item):
47 if isinstance(test_item, type) and issubclass(test_item, TestCase):
48 test_item.__unittest_skip__ = True
49 test_item.__unittest_skip_why__ = reason
50 return test_item
51 @functools.wraps(test_item)
52 def skip_wrapper(*args, **kwargs):
53 raise SkipTest(reason)
54 return skip_wrapper
55 return decorator
56
57def skipIf(condition, reason):
58 """
59 Skip a test if the condition is true.
60 """
61 if condition:
62 return skip(reason)
63 return _id
64
65def skipUnless(condition, reason):
66 """
67 Skip a test unless the condition is true.
68 """
69 if not condition:
70 return skip(reason)
71 return _id
72
73
74def expectedFailure(func):
75 @functools.wraps(func)
76 def wrapper(*args, **kwargs):
77 try:
78 func(*args, **kwargs)
79 except Exception:
80 raise _ExpectedFailure(sys.exc_info())
81 raise _UnexpectedSuccess
82 return wrapper
83
84
85class _AssertRaisesContext(object):
86 """A context manager used to implement TestCase.assertRaises* methods."""
87
88 def __init__(self, expected, test_case, callable_obj=None,
89 expected_regexp=None):
90 self.expected = expected
91 self.failureException = test_case.failureException
92 if callable_obj is not None:
93 try:
94 self.obj_name = callable_obj.__name__
95 except AttributeError:
96 self.obj_name = str(callable_obj)
97 else:
98 self.obj_name = None
99 self.expected_regex = expected_regexp
100
101 def __enter__(self):
102 pass
103
104 def __exit__(self, exc_type, exc_value, tb):
105 if exc_type is None:
106 try:
107 exc_name = self.expected.__name__
108 except AttributeError:
109 exc_name = str(self.expected)
110 if self.obj_name:
111 raise self.failureException("{0} not raised by {1}"
112 .format(exc_name, self.obj_name))
113 else:
114 raise self.failureException("{0} not raised"
115 .format(exc_name))
116 if not issubclass(exc_type, self.expected):
117 # let unexpected exceptions pass through
118 return False
Benjamin Peterson9a779ea2009-10-04 20:07:34 +0000119 self.exc_value = exc_value #store for later retrieval
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000120 if self.expected_regex is None:
121 return True
122
123 expected_regexp = self.expected_regex
124 if isinstance(expected_regexp, (bytes, str)):
125 expected_regexp = re.compile(expected_regexp)
126 if not expected_regexp.search(str(exc_value)):
127 raise self.failureException('"%s" does not match "%s"' %
128 (expected_regexp.pattern, str(exc_value)))
129 return True
130
131
132class _AssertWrapper(object):
133 """Wrap entries in the _type_equality_funcs registry to make them deep
134 copyable."""
135
136 def __init__(self, function):
137 self.function = function
138
139 def __deepcopy__(self, memo):
140 memo[id(self)] = self
141
142
143class TestCase(object):
144 """A class whose instances are single test cases.
145
146 By default, the test code itself should be placed in a method named
147 'runTest'.
148
149 If the fixture may be used for many test cases, create as
150 many test methods as are needed. When instantiating such a TestCase
151 subclass, specify in the constructor arguments the name of the test method
152 that the instance is to execute.
153
154 Test authors should subclass TestCase for their own tests. Construction
155 and deconstruction of the test's environment ('fixture') can be
156 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
157
158 If it is necessary to override the __init__ method, the base class
159 __init__ method must always be called. It is important that subclasses
160 should not change the signature of their __init__ method, since instances
161 of the classes are instantiated automatically by parts of the framework
162 in order to be run.
163 """
164
165 # This attribute determines which exception will be raised when
166 # the instance's assertion methods fail; test methods raising this
167 # exception will be deemed to have 'failed' rather than 'errored'
168
169 failureException = AssertionError
170
171 # This attribute determines whether long messages (including repr of
172 # objects used in assert methods) will be printed on failure in *addition*
173 # to any explicit message passed.
174
175 longMessage = False
176
177
178 def __init__(self, methodName='runTest'):
179 """Create an instance of the class that will use the named test
180 method when executed. Raises a ValueError if the instance does
181 not have a method with the specified name.
182 """
183 self._testMethodName = methodName
184 self._resultForDoCleanups = None
185 try:
186 testMethod = getattr(self, methodName)
187 except AttributeError:
188 raise ValueError("no such test method in %s: %s" % \
189 (self.__class__, methodName))
190 self._testMethodDoc = testMethod.__doc__
191 self._cleanups = []
192
193 # Map types to custom assertEqual functions that will compare
194 # instances of said type in more detail to generate a more useful
195 # error message.
196 self._type_equality_funcs = {}
197 self.addTypeEqualityFunc(dict, self.assertDictEqual)
198 self.addTypeEqualityFunc(list, self.assertListEqual)
199 self.addTypeEqualityFunc(tuple, self.assertTupleEqual)
200 self.addTypeEqualityFunc(set, self.assertSetEqual)
201 self.addTypeEqualityFunc(frozenset, self.assertSetEqual)
202
203 def addTypeEqualityFunc(self, typeobj, function):
204 """Add a type specific assertEqual style function to compare a type.
205
206 This method is for use by TestCase subclasses that need to register
207 their own type equality functions to provide nicer error messages.
208
209 Args:
210 typeobj: The data type to call this function on when both values
211 are of the same type in assertEqual().
212 function: The callable taking two arguments and an optional
213 msg= argument that raises self.failureException with a
214 useful error message when the two arguments are not equal.
215 """
216 self._type_equality_funcs[typeobj] = _AssertWrapper(function)
217
218 def addCleanup(self, function, *args, **kwargs):
219 """Add a function, with arguments, to be called when the test is
220 completed. Functions added are called on a LIFO basis and are
221 called after tearDown on test failure or success.
222
223 Cleanup items are called even if setUp fails (unlike tearDown)."""
224 self._cleanups.append((function, args, kwargs))
225
226 def setUp(self):
227 "Hook method for setting up the test fixture before exercising it."
228 pass
229
230 def tearDown(self):
231 "Hook method for deconstructing the test fixture after testing it."
232 pass
233
234 def countTestCases(self):
235 return 1
236
237 def defaultTestResult(self):
238 return result.TestResult()
239
240 def shortDescription(self):
241 """Returns both the test method name and first line of its docstring.
242
243 If no docstring is given, only returns the method name.
244
245 This method overrides unittest.TestCase.shortDescription(), which
246 only returns the first line of the docstring, obscuring the name
247 of the test upon failure.
248 """
249 desc = str(self)
250 doc_first_line = None
251
252 if self._testMethodDoc:
253 doc_first_line = self._testMethodDoc.split("\n")[0].strip()
254 if doc_first_line:
255 desc = '\n'.join((desc, doc_first_line))
256 return desc
257
258 def id(self):
259 return "%s.%s" % (util.strclass(self.__class__), self._testMethodName)
260
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):
274 return "%s (%s)" % (self._testMethodName, util.strclass(self.__class__))
275
276 def __repr__(self):
277 return "<%s testMethod=%s>" % \
278 (util.strclass(self.__class__), self._testMethodName)
279
280 def run(self, result=None):
281 orig_result = result
282 if result is None:
283 result = self.defaultTestResult()
284 startTestRun = getattr(result, 'startTestRun', None)
285 if startTestRun is not None:
286 startTestRun()
287
288 self._resultForDoCleanups = result
289 result.startTest(self)
290 if getattr(self.__class__, "__unittest_skip__", False):
291 # If the whole class was skipped.
292 try:
293 result.addSkip(self, self.__class__.__unittest_skip_why__)
294 finally:
295 result.stopTest(self)
296 return
297 testMethod = getattr(self, self._testMethodName)
298 try:
299 success = False
300 try:
301 self.setUp()
302 except SkipTest as e:
303 result.addSkip(self, str(e))
304 except Exception:
305 result.addError(self, sys.exc_info())
306 else:
307 try:
308 testMethod()
309 except self.failureException:
310 result.addFailure(self, sys.exc_info())
311 except _ExpectedFailure as e:
312 result.addExpectedFailure(self, e.exc_info)
313 except _UnexpectedSuccess:
314 result.addUnexpectedSuccess(self)
315 except SkipTest as e:
316 result.addSkip(self, str(e))
317 except Exception:
318 result.addError(self, sys.exc_info())
319 else:
320 success = True
321
322 try:
323 self.tearDown()
324 except Exception:
325 result.addError(self, sys.exc_info())
326 success = False
327
328 cleanUpSuccess = self.doCleanups()
329 success = success and cleanUpSuccess
330 if success:
331 result.addSuccess(self)
332 finally:
333 result.stopTest(self)
334 if orig_result is None:
335 stopTestRun = getattr(result, 'stopTestRun', None)
336 if stopTestRun is not None:
337 stopTestRun()
338
339 def doCleanups(self):
340 """Execute all cleanup functions. Normally called for you after
341 tearDown."""
342 result = self._resultForDoCleanups
343 ok = True
344 while self._cleanups:
345 function, args, kwargs = self._cleanups.pop(-1)
346 try:
347 function(*args, **kwargs)
348 except Exception:
349 ok = False
350 result.addError(self, sys.exc_info())
351 return ok
352
353 def __call__(self, *args, **kwds):
354 return self.run(*args, **kwds)
355
356 def debug(self):
357 """Run the test without collecting errors in a TestResult"""
358 self.setUp()
359 getattr(self, self._testMethodName)()
360 self.tearDown()
361
362 def skipTest(self, reason):
363 """Skip this test."""
364 raise SkipTest(reason)
365
366 def fail(self, msg=None):
367 """Fail immediately, with the given message."""
368 raise self.failureException(msg)
369
370 def assertFalse(self, expr, msg=None):
371 "Fail the test if the expression is true."
372 if expr:
373 msg = self._formatMessage(msg, "%r is not False" % expr)
374 raise self.failureException(msg)
375
376 def assertTrue(self, expr, msg=None):
377 """Fail the test unless the expression is true."""
378 if not expr:
379 msg = self._formatMessage(msg, "%r is not True" % expr)
380 raise self.failureException(msg)
381
382 def _formatMessage(self, msg, standardMsg):
383 """Honour the longMessage attribute when generating failure messages.
384 If longMessage is False this means:
385 * Use only an explicit message if it is provided
386 * Otherwise use the standard message for the assert
387
388 If longMessage is True:
389 * Use the standard message
390 * If an explicit message is provided, plus ' : ' and the explicit message
391 """
392 if not self.longMessage:
393 return msg or standardMsg
394 if msg is None:
395 return standardMsg
396 return standardMsg + ' : ' + msg
397
398
399 def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
400 """Fail unless an exception of class excClass is thrown
401 by callableObj when invoked with arguments args and keyword
402 arguments kwargs. If a different type of exception is
403 thrown, it will not be caught, and the test case will be
404 deemed to have suffered an error, exactly as for an
405 unexpected exception.
406
407 If called with callableObj omitted or None, will return a
408 context object used like this::
409
410 with self.assertRaises(some_error_class):
411 do_something()
412 """
413 context = _AssertRaisesContext(excClass, self, callableObj)
414 if callableObj is None:
415 return context
416 with context:
417 callableObj(*args, **kwargs)
418
419 def _getAssertEqualityFunc(self, first, second):
420 """Get a detailed comparison function for the types of the two args.
421
422 Returns: A callable accepting (first, second, msg=None) that will
423 raise a failure exception if first != second with a useful human
424 readable error message for those types.
425 """
426 #
427 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
428 # and vice versa. I opted for the conservative approach in case
429 # subclasses are not intended to be compared in detail to their super
430 # class instances using a type equality func. This means testing
431 # subtypes won't automagically use the detailed comparison. Callers
432 # should use their type specific assertSpamEqual method to compare
433 # subclasses if the detailed comparison is desired and appropriate.
434 # See the discussion in http://bugs.python.org/issue2578.
435 #
436 if type(first) is type(second):
437 asserter = self._type_equality_funcs.get(type(first))
438 if asserter is not None:
439 return asserter.function
440
441 return self._baseAssertEqual
442
443 def _baseAssertEqual(self, first, second, msg=None):
444 """The default assertEqual implementation, not type specific."""
445 if not first == second:
446 standardMsg = '%r != %r' % (first, second)
447 msg = self._formatMessage(msg, standardMsg)
448 raise self.failureException(msg)
449
450 def assertEqual(self, first, second, msg=None):
451 """Fail if the two objects are unequal as determined by the '=='
452 operator.
453 """
454 assertion_func = self._getAssertEqualityFunc(first, second)
455 assertion_func(first, second, msg=msg)
456
457 def assertNotEqual(self, first, second, msg=None):
458 """Fail if the two objects are equal as determined by the '=='
459 operator.
460 """
461 if not first != second:
462 msg = self._formatMessage(msg, '%r == %r' % (first, second))
463 raise self.failureException(msg)
464
465 def assertAlmostEqual(self, first, second, *, places=7, msg=None):
466 """Fail if the two objects are unequal as determined by their
467 difference rounded to the given number of decimal places
468 (default 7) and comparing to zero.
469
470 Note that decimal places (from zero) are usually not the same
471 as significant digits (measured from the most signficant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000472
473 If the two objects compare equal then they will automatically
474 compare almost equal.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000475 """
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000476 if first == second:
477 # shortcut for ite
478 return
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000479 if round(abs(second-first), places) != 0:
480 standardMsg = '%r != %r within %r places' % (first, second, places)
481 msg = self._formatMessage(msg, standardMsg)
482 raise self.failureException(msg)
483
484 def assertNotAlmostEqual(self, first, second, *, places=7, msg=None):
485 """Fail if the two objects are equal as determined by their
486 difference rounded to the given number of decimal places
487 (default 7) and comparing to zero.
488
489 Note that decimal places (from zero) are usually not the same
490 as significant digits (measured from the most signficant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000491
492 Objects that are equal automatically fail.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000493 """
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000494 if (first == second) or round(abs(second-first), places) == 0:
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000495 standardMsg = '%r == %r within %r places' % (first, second, places)
496 msg = self._formatMessage(msg, standardMsg)
497 raise self.failureException(msg)
498
499 # Synonyms for assertion methods
500
501 # The plurals are undocumented. Keep them that way to discourage use.
502 # Do not add more. Do not remove.
503 # Going through a deprecation cycle on these would annoy many people.
504 assertEquals = assertEqual
505 assertNotEquals = assertNotEqual
506 assertAlmostEquals = assertAlmostEqual
507 assertNotAlmostEquals = assertNotAlmostEqual
508 assert_ = assertTrue
509
510 # These fail* assertion method names are pending deprecation and will
511 # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
512 def _deprecate(original_func):
513 def deprecated_func(*args, **kwargs):
514 warnings.warn(
515 'Please use {0} instead.'.format(original_func.__name__),
516 DeprecationWarning, 2)
517 return original_func(*args, **kwargs)
518 return deprecated_func
519
520 failUnlessEqual = _deprecate(assertEqual)
521 failIfEqual = _deprecate(assertNotEqual)
522 failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
523 failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
524 failUnless = _deprecate(assertTrue)
525 failUnlessRaises = _deprecate(assertRaises)
526 failIf = _deprecate(assertFalse)
527
528 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
529 """An equality assertion for ordered sequences (like lists and tuples).
530
531 For the purposes of this function, a valid orderd sequence type is one
532 which can be indexed, has a length, and has an equality operator.
533
534 Args:
535 seq1: The first sequence to compare.
536 seq2: The second sequence to compare.
537 seq_type: The expected datatype of the sequences, or None if no
538 datatype should be enforced.
539 msg: Optional message to use on failure instead of a list of
540 differences.
541 """
542 if seq_type != None:
543 seq_type_name = seq_type.__name__
544 if not isinstance(seq1, seq_type):
545 raise self.failureException('First sequence is not a %s: %r'
546 % (seq_type_name, seq1))
547 if not isinstance(seq2, seq_type):
548 raise self.failureException('Second sequence is not a %s: %r'
549 % (seq_type_name, seq2))
550 else:
551 seq_type_name = "sequence"
552
553 differing = None
554 try:
555 len1 = len(seq1)
556 except (TypeError, NotImplementedError):
557 differing = 'First %s has no length. Non-sequence?' % (
558 seq_type_name)
559
560 if differing is None:
561 try:
562 len2 = len(seq2)
563 except (TypeError, NotImplementedError):
564 differing = 'Second %s has no length. Non-sequence?' % (
565 seq_type_name)
566
567 if differing is None:
568 if seq1 == seq2:
569 return
570
571 seq1_repr = repr(seq1)
572 seq2_repr = repr(seq2)
573 if len(seq1_repr) > 30:
574 seq1_repr = seq1_repr[:30] + '...'
575 if len(seq2_repr) > 30:
576 seq2_repr = seq2_repr[:30] + '...'
577 elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
578 differing = '%ss differ: %s != %s\n' % elements
579
580 for i in range(min(len1, len2)):
581 try:
582 item1 = seq1[i]
583 except (TypeError, IndexError, NotImplementedError):
584 differing += ('\nUnable to index element %d of first %s\n' %
585 (i, seq_type_name))
586 break
587
588 try:
589 item2 = seq2[i]
590 except (TypeError, IndexError, NotImplementedError):
591 differing += ('\nUnable to index element %d of second %s\n' %
592 (i, seq_type_name))
593 break
594
595 if item1 != item2:
596 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
597 (i, item1, item2))
598 break
599 else:
600 if (len1 == len2 and seq_type is None and
601 type(seq1) != type(seq2)):
602 # The sequences are the same, but have differing types.
603 return
604
605 if len1 > len2:
606 differing += ('\nFirst %s contains %d additional '
607 'elements.\n' % (seq_type_name, len1 - len2))
608 try:
609 differing += ('First extra element %d:\n%s\n' %
610 (len2, seq1[len2]))
611 except (TypeError, IndexError, NotImplementedError):
612 differing += ('Unable to index element %d '
613 'of first %s\n' % (len2, seq_type_name))
614 elif len1 < len2:
615 differing += ('\nSecond %s contains %d additional '
616 'elements.\n' % (seq_type_name, len2 - len1))
617 try:
618 differing += ('First extra element %d:\n%s\n' %
619 (len1, seq2[len1]))
620 except (TypeError, IndexError, NotImplementedError):
621 differing += ('Unable to index element %d '
622 'of second %s\n' % (len1, seq_type_name))
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000623 standardMsg = differing + '\n' + '\n'.join(
624 difflib.ndiff(pprint.pformat(seq1).splitlines(),
625 pprint.pformat(seq2).splitlines()))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000626 msg = self._formatMessage(msg, standardMsg)
627 self.fail(msg)
628
629 def assertListEqual(self, list1, list2, msg=None):
630 """A list-specific equality assertion.
631
632 Args:
633 list1: The first list to compare.
634 list2: The second list to compare.
635 msg: Optional message to use on failure instead of a list of
636 differences.
637
638 """
639 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
640
641 def assertTupleEqual(self, tuple1, tuple2, msg=None):
642 """A tuple-specific equality assertion.
643
644 Args:
645 tuple1: The first tuple to compare.
646 tuple2: The second tuple to compare.
647 msg: Optional message to use on failure instead of a list of
648 differences.
649 """
650 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
651
652 def assertSetEqual(self, set1, set2, msg=None):
653 """A set-specific equality assertion.
654
655 Args:
656 set1: The first set to compare.
657 set2: The second set to compare.
658 msg: Optional message to use on failure instead of a list of
659 differences.
660
661 For more general containership equality, assertSameElements will work
662 with things other than sets. This uses ducktyping to support
663 different types of sets, and is optimized for sets specifically
664 (parameters must support a difference method).
665 """
666 try:
667 difference1 = set1.difference(set2)
668 except TypeError as e:
669 self.fail('invalid type when attempting set difference: %s' % e)
670 except AttributeError as e:
671 self.fail('first argument does not support set difference: %s' % e)
672
673 try:
674 difference2 = set2.difference(set1)
675 except TypeError as e:
676 self.fail('invalid type when attempting set difference: %s' % e)
677 except AttributeError as e:
678 self.fail('second argument does not support set difference: %s' % e)
679
680 if not (difference1 or difference2):
681 return
682
683 lines = []
684 if difference1:
685 lines.append('Items in the first set but not the second:')
686 for item in difference1:
687 lines.append(repr(item))
688 if difference2:
689 lines.append('Items in the second set but not the first:')
690 for item in difference2:
691 lines.append(repr(item))
692
693 standardMsg = '\n'.join(lines)
694 self.fail(self._formatMessage(msg, standardMsg))
695
696 def assertIn(self, member, container, msg=None):
697 """Just like self.assertTrue(a in b), but with a nicer default message."""
698 if member not in container:
699 standardMsg = '%r not found in %r' % (member, container)
700 self.fail(self._formatMessage(msg, standardMsg))
701
702 def assertNotIn(self, member, container, msg=None):
703 """Just like self.assertTrue(a not in b), but with a nicer default message."""
704 if member in container:
705 standardMsg = '%r unexpectedly found in %r' % (member, container)
706 self.fail(self._formatMessage(msg, standardMsg))
707
708 def assertIs(self, expr1, expr2, msg=None):
709 """Just like self.assertTrue(a is b), but with a nicer default message."""
710 if expr1 is not expr2:
711 standardMsg = '%r is not %r' % (expr1, expr2)
712 self.fail(self._formatMessage(msg, standardMsg))
713
714 def assertIsNot(self, expr1, expr2, msg=None):
715 """Just like self.assertTrue(a is not b), but with a nicer default message."""
716 if expr1 is expr2:
717 standardMsg = 'unexpectedly identical: %r' % (expr1,)
718 self.fail(self._formatMessage(msg, standardMsg))
719
720 def assertDictEqual(self, d1, d2, msg=None):
721 self.assert_(isinstance(d1, dict), 'First argument is not a dictionary')
722 self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary')
723
724 if d1 != d2:
725 standardMsg = ('\n' + '\n'.join(difflib.ndiff(
726 pprint.pformat(d1).splitlines(),
727 pprint.pformat(d2).splitlines())))
728 self.fail(self._formatMessage(msg, standardMsg))
729
730 def assertDictContainsSubset(self, expected, actual, msg=None):
731 """Checks whether actual is a superset of expected."""
732 missing = []
733 mismatched = []
734 for key, value in expected.items():
735 if key not in actual:
736 missing.append(key)
737 elif value != actual[key]:
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000738 mismatched.append('%s, expected: %s, actual: %s' %
739 (key, value, actual[key]))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000740
741 if not (missing or mismatched):
742 return
743
744 standardMsg = ''
745 if missing:
746 standardMsg = 'Missing: %r' % ','.join(missing)
747 if mismatched:
748 if standardMsg:
749 standardMsg += '; '
750 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
751
752 self.fail(self._formatMessage(msg, standardMsg))
753
754 def assertSameElements(self, expected_seq, actual_seq, msg=None):
755 """An unordered sequence specific comparison.
756
757 Raises with an error message listing which elements of expected_seq
758 are missing from actual_seq and vice versa if any.
759 """
760 try:
761 expected = set(expected_seq)
762 actual = set(actual_seq)
763 missing = list(expected.difference(actual))
764 unexpected = list(actual.difference(expected))
765 missing.sort()
766 unexpected.sort()
767 except TypeError:
768 # Fall back to slower list-compare if any of the objects are
769 # not hashable.
770 expected = list(expected_seq)
771 actual = list(actual_seq)
772 try:
773 expected.sort()
774 actual.sort()
775 except TypeError:
776 missing, unexpected = util.unorderable_list_difference(expected,
777 actual)
778 else:
779 missing, unexpected = util.sorted_list_difference(expected,
780 actual)
781 errors = []
782 if missing:
783 errors.append('Expected, but missing:\n %r' % missing)
784 if unexpected:
785 errors.append('Unexpected, but present:\n %r' % unexpected)
786 if errors:
787 standardMsg = '\n'.join(errors)
788 self.fail(self._formatMessage(msg, standardMsg))
789
790 def assertMultiLineEqual(self, first, second, msg=None):
791 """Assert that two multi-line strings are equal."""
792 self.assert_(isinstance(first, str), (
793 'First argument is not a string'))
794 self.assert_(isinstance(second, str), (
795 'Second argument is not a string'))
796
797 if first != second:
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000798 standardMsg = '\n' + ''.join(difflib.ndiff(first.splitlines(True),
799 second.splitlines(True)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000800 self.fail(self._formatMessage(msg, standardMsg))
801
802 def assertLess(self, a, b, msg=None):
803 """Just like self.assertTrue(a < b), but with a nicer default message."""
804 if not a < b:
805 standardMsg = '%r not less than %r' % (a, b)
806 self.fail(self._formatMessage(msg, standardMsg))
807
808 def assertLessEqual(self, a, b, msg=None):
809 """Just like self.assertTrue(a <= b), but with a nicer default message."""
810 if not a <= b:
811 standardMsg = '%r not less than or equal to %r' % (a, b)
812 self.fail(self._formatMessage(msg, standardMsg))
813
814 def assertGreater(self, a, b, msg=None):
815 """Just like self.assertTrue(a > b), but with a nicer default message."""
816 if not a > b:
817 standardMsg = '%r not greater than %r' % (a, b)
818 self.fail(self._formatMessage(msg, standardMsg))
819
820 def assertGreaterEqual(self, a, b, msg=None):
821 """Just like self.assertTrue(a >= b), but with a nicer default message."""
822 if not a >= b:
823 standardMsg = '%r not greater than or equal to %r' % (a, b)
824 self.fail(self._formatMessage(msg, standardMsg))
825
826 def assertIsNone(self, obj, msg=None):
827 """Same as self.assertTrue(obj is None), with a nicer default message."""
828 if obj is not None:
829 standardMsg = '%r is not None' % obj
830 self.fail(self._formatMessage(msg, standardMsg))
831
832 def assertIsNotNone(self, obj, msg=None):
833 """Included for symmetry with assertIsNone."""
834 if obj is None:
835 standardMsg = 'unexpectedly None'
836 self.fail(self._formatMessage(msg, standardMsg))
837
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000838 def assertIsInstance(self, obj, cls, msg=None):
839 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
840 default message."""
841 if not isinstance(obj, cls):
842 standardMsg = '%r is not an instance of %r' % (obj, cls)
843 self.fail(self._formatMessage(msg, standardMsg))
844
845 def assertNotIsInstance(self, obj, cls, msg=None):
846 """Included for symmetry with assertIsInstance."""
847 if isinstance(obj, cls):
848 standardMsg = '%r is an instance of %r' % (obj, cls)
849 self.fail(self._formatMessage(msg, standardMsg))
850
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000851 def assertRaisesRegexp(self, expected_exception, expected_regexp,
852 callable_obj=None, *args, **kwargs):
853 """Asserts that the message in a raised exception matches a regexp.
854
855 Args:
856 expected_exception: Exception class expected to be raised.
857 expected_regexp: Regexp (re pattern object or string) expected
858 to be found in error message.
859 callable_obj: Function to be called.
860 args: Extra args.
861 kwargs: Extra kwargs.
862 """
863 context = _AssertRaisesContext(expected_exception, self, callable_obj,
864 expected_regexp)
865 if callable_obj is None:
866 return context
867 with context:
868 callable_obj(*args, **kwargs)
869
870 def assertRegexpMatches(self, text, expected_regex, msg=None):
871 if isinstance(expected_regex, (str, bytes)):
872 expected_regex = re.compile(expected_regex)
873 if not expected_regex.search(text):
874 msg = msg or "Regexp didn't match"
875 msg = '%s: %r not found in %r' % (msg, expected_regex.pattern, text)
876 raise self.failureException(msg)
877
878
879class FunctionTestCase(TestCase):
880 """A test case that wraps a test function.
881
882 This is useful for slipping pre-existing test functions into the
883 unittest framework. Optionally, set-up and tidy-up functions can be
884 supplied. As with TestCase, the tidy-up ('tearDown') function will
885 always be called if the set-up ('setUp') function ran successfully.
886 """
887
888 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
889 super(FunctionTestCase, self).__init__()
890 self._setUpFunc = setUp
891 self._tearDownFunc = tearDown
892 self._testFunc = testFunc
893 self._description = description
894
895 def setUp(self):
896 if self._setUpFunc is not None:
897 self._setUpFunc()
898
899 def tearDown(self):
900 if self._tearDownFunc is not None:
901 self._tearDownFunc()
902
903 def runTest(self):
904 self._testFunc()
905
906 def id(self):
907 return self._testFunc.__name__
908
909 def __eq__(self, other):
910 if not isinstance(other, self.__class__):
911 return NotImplemented
912
913 return self._setUpFunc == other._setUpFunc and \
914 self._tearDownFunc == other._tearDownFunc and \
915 self._testFunc == other._testFunc and \
916 self._description == other._description
917
918 def __ne__(self, other):
919 return not self == other
920
921 def __hash__(self):
922 return hash((type(self), self._setUpFunc, self._tearDownFunc,
923 self._testFunc, self._description))
924
925 def __str__(self):
926 return "%s (%s)" % (util.strclass(self.__class__),
927 self._testFunc.__name__)
928
929 def __repr__(self):
930 return "<%s testFunc=%s>" % (util.strclass(self.__class__),
931 self._testFunc)
932
933 def shortDescription(self):
934 if self._description is not None:
935 return self._description
936 doc = self._testFunc.__doc__
937 return doc and doc.split("\n")[0].strip() or None