blob: 660ddebccae983baa192bd3a8efb00d0d2bb730c [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))
623 standardMsg = differing + '\n' + '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(),
624 pprint.pformat(seq2).splitlines()))
625 msg = self._formatMessage(msg, standardMsg)
626 self.fail(msg)
627
628 def assertListEqual(self, list1, list2, msg=None):
629 """A list-specific equality assertion.
630
631 Args:
632 list1: The first list to compare.
633 list2: The second list to compare.
634 msg: Optional message to use on failure instead of a list of
635 differences.
636
637 """
638 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
639
640 def assertTupleEqual(self, tuple1, tuple2, msg=None):
641 """A tuple-specific equality assertion.
642
643 Args:
644 tuple1: The first tuple to compare.
645 tuple2: The second tuple to compare.
646 msg: Optional message to use on failure instead of a list of
647 differences.
648 """
649 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
650
651 def assertSetEqual(self, set1, set2, msg=None):
652 """A set-specific equality assertion.
653
654 Args:
655 set1: The first set to compare.
656 set2: The second set to compare.
657 msg: Optional message to use on failure instead of a list of
658 differences.
659
660 For more general containership equality, assertSameElements will work
661 with things other than sets. This uses ducktyping to support
662 different types of sets, and is optimized for sets specifically
663 (parameters must support a difference method).
664 """
665 try:
666 difference1 = set1.difference(set2)
667 except TypeError as e:
668 self.fail('invalid type when attempting set difference: %s' % e)
669 except AttributeError as e:
670 self.fail('first argument does not support set difference: %s' % e)
671
672 try:
673 difference2 = set2.difference(set1)
674 except TypeError as e:
675 self.fail('invalid type when attempting set difference: %s' % e)
676 except AttributeError as e:
677 self.fail('second argument does not support set difference: %s' % e)
678
679 if not (difference1 or difference2):
680 return
681
682 lines = []
683 if difference1:
684 lines.append('Items in the first set but not the second:')
685 for item in difference1:
686 lines.append(repr(item))
687 if difference2:
688 lines.append('Items in the second set but not the first:')
689 for item in difference2:
690 lines.append(repr(item))
691
692 standardMsg = '\n'.join(lines)
693 self.fail(self._formatMessage(msg, standardMsg))
694
695 def assertIn(self, member, container, msg=None):
696 """Just like self.assertTrue(a in b), but with a nicer default message."""
697 if member not in container:
698 standardMsg = '%r not found in %r' % (member, container)
699 self.fail(self._formatMessage(msg, standardMsg))
700
701 def assertNotIn(self, member, container, msg=None):
702 """Just like self.assertTrue(a not in b), but with a nicer default message."""
703 if member in container:
704 standardMsg = '%r unexpectedly found in %r' % (member, container)
705 self.fail(self._formatMessage(msg, standardMsg))
706
707 def assertIs(self, expr1, expr2, msg=None):
708 """Just like self.assertTrue(a is b), but with a nicer default message."""
709 if expr1 is not expr2:
710 standardMsg = '%r is not %r' % (expr1, expr2)
711 self.fail(self._formatMessage(msg, standardMsg))
712
713 def assertIsNot(self, expr1, expr2, msg=None):
714 """Just like self.assertTrue(a is not b), but with a nicer default message."""
715 if expr1 is expr2:
716 standardMsg = 'unexpectedly identical: %r' % (expr1,)
717 self.fail(self._formatMessage(msg, standardMsg))
718
719 def assertDictEqual(self, d1, d2, msg=None):
720 self.assert_(isinstance(d1, dict), 'First argument is not a dictionary')
721 self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary')
722
723 if d1 != d2:
724 standardMsg = ('\n' + '\n'.join(difflib.ndiff(
725 pprint.pformat(d1).splitlines(),
726 pprint.pformat(d2).splitlines())))
727 self.fail(self._formatMessage(msg, standardMsg))
728
729 def assertDictContainsSubset(self, expected, actual, msg=None):
730 """Checks whether actual is a superset of expected."""
731 missing = []
732 mismatched = []
733 for key, value in expected.items():
734 if key not in actual:
735 missing.append(key)
736 elif value != actual[key]:
737 mismatched.append('%s, expected: %s, actual: %s' % (key, value, actual[key]))
738
739 if not (missing or mismatched):
740 return
741
742 standardMsg = ''
743 if missing:
744 standardMsg = 'Missing: %r' % ','.join(missing)
745 if mismatched:
746 if standardMsg:
747 standardMsg += '; '
748 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
749
750 self.fail(self._formatMessage(msg, standardMsg))
751
752 def assertSameElements(self, expected_seq, actual_seq, msg=None):
753 """An unordered sequence specific comparison.
754
755 Raises with an error message listing which elements of expected_seq
756 are missing from actual_seq and vice versa if any.
757 """
758 try:
759 expected = set(expected_seq)
760 actual = set(actual_seq)
761 missing = list(expected.difference(actual))
762 unexpected = list(actual.difference(expected))
763 missing.sort()
764 unexpected.sort()
765 except TypeError:
766 # Fall back to slower list-compare if any of the objects are
767 # not hashable.
768 expected = list(expected_seq)
769 actual = list(actual_seq)
770 try:
771 expected.sort()
772 actual.sort()
773 except TypeError:
774 missing, unexpected = util.unorderable_list_difference(expected,
775 actual)
776 else:
777 missing, unexpected = util.sorted_list_difference(expected,
778 actual)
779 errors = []
780 if missing:
781 errors.append('Expected, but missing:\n %r' % missing)
782 if unexpected:
783 errors.append('Unexpected, but present:\n %r' % unexpected)
784 if errors:
785 standardMsg = '\n'.join(errors)
786 self.fail(self._formatMessage(msg, standardMsg))
787
788 def assertMultiLineEqual(self, first, second, msg=None):
789 """Assert that two multi-line strings are equal."""
790 self.assert_(isinstance(first, str), (
791 'First argument is not a string'))
792 self.assert_(isinstance(second, str), (
793 'Second argument is not a string'))
794
795 if first != second:
796 standardMsg = '\n' + ''.join(difflib.ndiff(first.splitlines(True), second.splitlines(True)))
797 self.fail(self._formatMessage(msg, standardMsg))
798
799 def assertLess(self, a, b, msg=None):
800 """Just like self.assertTrue(a < b), but with a nicer default message."""
801 if not a < b:
802 standardMsg = '%r not less than %r' % (a, b)
803 self.fail(self._formatMessage(msg, standardMsg))
804
805 def assertLessEqual(self, a, b, msg=None):
806 """Just like self.assertTrue(a <= b), but with a nicer default message."""
807 if not a <= b:
808 standardMsg = '%r not less than or equal to %r' % (a, b)
809 self.fail(self._formatMessage(msg, standardMsg))
810
811 def assertGreater(self, a, b, msg=None):
812 """Just like self.assertTrue(a > b), but with a nicer default message."""
813 if not a > b:
814 standardMsg = '%r not greater than %r' % (a, b)
815 self.fail(self._formatMessage(msg, standardMsg))
816
817 def assertGreaterEqual(self, a, b, msg=None):
818 """Just like self.assertTrue(a >= b), but with a nicer default message."""
819 if not a >= b:
820 standardMsg = '%r not greater than or equal to %r' % (a, b)
821 self.fail(self._formatMessage(msg, standardMsg))
822
823 def assertIsNone(self, obj, msg=None):
824 """Same as self.assertTrue(obj is None), with a nicer default message."""
825 if obj is not None:
826 standardMsg = '%r is not None' % obj
827 self.fail(self._formatMessage(msg, standardMsg))
828
829 def assertIsNotNone(self, obj, msg=None):
830 """Included for symmetry with assertIsNone."""
831 if obj is None:
832 standardMsg = 'unexpectedly None'
833 self.fail(self._formatMessage(msg, standardMsg))
834
835 def assertRaisesRegexp(self, expected_exception, expected_regexp,
836 callable_obj=None, *args, **kwargs):
837 """Asserts that the message in a raised exception matches a regexp.
838
839 Args:
840 expected_exception: Exception class expected to be raised.
841 expected_regexp: Regexp (re pattern object or string) expected
842 to be found in error message.
843 callable_obj: Function to be called.
844 args: Extra args.
845 kwargs: Extra kwargs.
846 """
847 context = _AssertRaisesContext(expected_exception, self, callable_obj,
848 expected_regexp)
849 if callable_obj is None:
850 return context
851 with context:
852 callable_obj(*args, **kwargs)
853
854 def assertRegexpMatches(self, text, expected_regex, msg=None):
855 if isinstance(expected_regex, (str, bytes)):
856 expected_regex = re.compile(expected_regex)
857 if not expected_regex.search(text):
858 msg = msg or "Regexp didn't match"
859 msg = '%s: %r not found in %r' % (msg, expected_regex.pattern, text)
860 raise self.failureException(msg)
861
862
863class FunctionTestCase(TestCase):
864 """A test case that wraps a test function.
865
866 This is useful for slipping pre-existing test functions into the
867 unittest framework. Optionally, set-up and tidy-up functions can be
868 supplied. As with TestCase, the tidy-up ('tearDown') function will
869 always be called if the set-up ('setUp') function ran successfully.
870 """
871
872 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
873 super(FunctionTestCase, self).__init__()
874 self._setUpFunc = setUp
875 self._tearDownFunc = tearDown
876 self._testFunc = testFunc
877 self._description = description
878
879 def setUp(self):
880 if self._setUpFunc is not None:
881 self._setUpFunc()
882
883 def tearDown(self):
884 if self._tearDownFunc is not None:
885 self._tearDownFunc()
886
887 def runTest(self):
888 self._testFunc()
889
890 def id(self):
891 return self._testFunc.__name__
892
893 def __eq__(self, other):
894 if not isinstance(other, self.__class__):
895 return NotImplemented
896
897 return self._setUpFunc == other._setUpFunc and \
898 self._tearDownFunc == other._tearDownFunc and \
899 self._testFunc == other._testFunc and \
900 self._description == other._description
901
902 def __ne__(self, other):
903 return not self == other
904
905 def __hash__(self):
906 return hash((type(self), self._setUpFunc, self._tearDownFunc,
907 self._testFunc, self._description))
908
909 def __str__(self):
910 return "%s (%s)" % (util.strclass(self.__class__),
911 self._testFunc.__name__)
912
913 def __repr__(self):
914 return "<%s testFunc=%s>" % (util.strclass(self.__class__),
915 self._testFunc)
916
917 def shortDescription(self):
918 if self._description is not None:
919 return self._description
920 doc = self._testFunc.__doc__
921 return doc and doc.split("\n")[0].strip() or None