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