blob: 48f3ef14988b93aad9dff3328a5ea18b3f640b2b [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).
471 """
472 if round(abs(second-first), places) != 0:
473 standardMsg = '%r != %r within %r places' % (first, second, places)
474 msg = self._formatMessage(msg, standardMsg)
475 raise self.failureException(msg)
476
477 def assertNotAlmostEqual(self, first, second, *, places=7, msg=None):
478 """Fail if the two objects are equal as determined by their
479 difference rounded to the given number of decimal places
480 (default 7) and comparing to zero.
481
482 Note that decimal places (from zero) are usually not the same
483 as significant digits (measured from the most signficant digit).
484 """
485 if round(abs(second-first), places) == 0:
486 standardMsg = '%r == %r within %r places' % (first, second, places)
487 msg = self._formatMessage(msg, standardMsg)
488 raise self.failureException(msg)
489
490 # Synonyms for assertion methods
491
492 # The plurals are undocumented. Keep them that way to discourage use.
493 # Do not add more. Do not remove.
494 # Going through a deprecation cycle on these would annoy many people.
495 assertEquals = assertEqual
496 assertNotEquals = assertNotEqual
497 assertAlmostEquals = assertAlmostEqual
498 assertNotAlmostEquals = assertNotAlmostEqual
499 assert_ = assertTrue
500
501 # These fail* assertion method names are pending deprecation and will
502 # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
503 def _deprecate(original_func):
504 def deprecated_func(*args, **kwargs):
505 warnings.warn(
506 'Please use {0} instead.'.format(original_func.__name__),
507 DeprecationWarning, 2)
508 return original_func(*args, **kwargs)
509 return deprecated_func
510
511 failUnlessEqual = _deprecate(assertEqual)
512 failIfEqual = _deprecate(assertNotEqual)
513 failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
514 failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
515 failUnless = _deprecate(assertTrue)
516 failUnlessRaises = _deprecate(assertRaises)
517 failIf = _deprecate(assertFalse)
518
519 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
520 """An equality assertion for ordered sequences (like lists and tuples).
521
522 For the purposes of this function, a valid orderd sequence type is one
523 which can be indexed, has a length, and has an equality operator.
524
525 Args:
526 seq1: The first sequence to compare.
527 seq2: The second sequence to compare.
528 seq_type: The expected datatype of the sequences, or None if no
529 datatype should be enforced.
530 msg: Optional message to use on failure instead of a list of
531 differences.
532 """
533 if seq_type != None:
534 seq_type_name = seq_type.__name__
535 if not isinstance(seq1, seq_type):
536 raise self.failureException('First sequence is not a %s: %r'
537 % (seq_type_name, seq1))
538 if not isinstance(seq2, seq_type):
539 raise self.failureException('Second sequence is not a %s: %r'
540 % (seq_type_name, seq2))
541 else:
542 seq_type_name = "sequence"
543
544 differing = None
545 try:
546 len1 = len(seq1)
547 except (TypeError, NotImplementedError):
548 differing = 'First %s has no length. Non-sequence?' % (
549 seq_type_name)
550
551 if differing is None:
552 try:
553 len2 = len(seq2)
554 except (TypeError, NotImplementedError):
555 differing = 'Second %s has no length. Non-sequence?' % (
556 seq_type_name)
557
558 if differing is None:
559 if seq1 == seq2:
560 return
561
562 seq1_repr = repr(seq1)
563 seq2_repr = repr(seq2)
564 if len(seq1_repr) > 30:
565 seq1_repr = seq1_repr[:30] + '...'
566 if len(seq2_repr) > 30:
567 seq2_repr = seq2_repr[:30] + '...'
568 elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
569 differing = '%ss differ: %s != %s\n' % elements
570
571 for i in range(min(len1, len2)):
572 try:
573 item1 = seq1[i]
574 except (TypeError, IndexError, NotImplementedError):
575 differing += ('\nUnable to index element %d of first %s\n' %
576 (i, seq_type_name))
577 break
578
579 try:
580 item2 = seq2[i]
581 except (TypeError, IndexError, NotImplementedError):
582 differing += ('\nUnable to index element %d of second %s\n' %
583 (i, seq_type_name))
584 break
585
586 if item1 != item2:
587 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
588 (i, item1, item2))
589 break
590 else:
591 if (len1 == len2 and seq_type is None and
592 type(seq1) != type(seq2)):
593 # The sequences are the same, but have differing types.
594 return
595
596 if len1 > len2:
597 differing += ('\nFirst %s contains %d additional '
598 'elements.\n' % (seq_type_name, len1 - len2))
599 try:
600 differing += ('First extra element %d:\n%s\n' %
601 (len2, seq1[len2]))
602 except (TypeError, IndexError, NotImplementedError):
603 differing += ('Unable to index element %d '
604 'of first %s\n' % (len2, seq_type_name))
605 elif len1 < len2:
606 differing += ('\nSecond %s contains %d additional '
607 'elements.\n' % (seq_type_name, len2 - len1))
608 try:
609 differing += ('First extra element %d:\n%s\n' %
610 (len1, seq2[len1]))
611 except (TypeError, IndexError, NotImplementedError):
612 differing += ('Unable to index element %d '
613 'of second %s\n' % (len1, seq_type_name))
614 standardMsg = differing + '\n' + '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(),
615 pprint.pformat(seq2).splitlines()))
616 msg = self._formatMessage(msg, standardMsg)
617 self.fail(msg)
618
619 def assertListEqual(self, list1, list2, msg=None):
620 """A list-specific equality assertion.
621
622 Args:
623 list1: The first list to compare.
624 list2: The second list to compare.
625 msg: Optional message to use on failure instead of a list of
626 differences.
627
628 """
629 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
630
631 def assertTupleEqual(self, tuple1, tuple2, msg=None):
632 """A tuple-specific equality assertion.
633
634 Args:
635 tuple1: The first tuple to compare.
636 tuple2: The second tuple to compare.
637 msg: Optional message to use on failure instead of a list of
638 differences.
639 """
640 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
641
642 def assertSetEqual(self, set1, set2, msg=None):
643 """A set-specific equality assertion.
644
645 Args:
646 set1: The first set to compare.
647 set2: The second set to compare.
648 msg: Optional message to use on failure instead of a list of
649 differences.
650
651 For more general containership equality, assertSameElements will work
652 with things other than sets. This uses ducktyping to support
653 different types of sets, and is optimized for sets specifically
654 (parameters must support a difference method).
655 """
656 try:
657 difference1 = set1.difference(set2)
658 except TypeError as e:
659 self.fail('invalid type when attempting set difference: %s' % e)
660 except AttributeError as e:
661 self.fail('first argument does not support set difference: %s' % e)
662
663 try:
664 difference2 = set2.difference(set1)
665 except TypeError as e:
666 self.fail('invalid type when attempting set difference: %s' % e)
667 except AttributeError as e:
668 self.fail('second argument does not support set difference: %s' % e)
669
670 if not (difference1 or difference2):
671 return
672
673 lines = []
674 if difference1:
675 lines.append('Items in the first set but not the second:')
676 for item in difference1:
677 lines.append(repr(item))
678 if difference2:
679 lines.append('Items in the second set but not the first:')
680 for item in difference2:
681 lines.append(repr(item))
682
683 standardMsg = '\n'.join(lines)
684 self.fail(self._formatMessage(msg, standardMsg))
685
686 def assertIn(self, member, container, msg=None):
687 """Just like self.assertTrue(a in b), but with a nicer default message."""
688 if member not in container:
689 standardMsg = '%r not found in %r' % (member, container)
690 self.fail(self._formatMessage(msg, standardMsg))
691
692 def assertNotIn(self, member, container, msg=None):
693 """Just like self.assertTrue(a not in b), but with a nicer default message."""
694 if member in container:
695 standardMsg = '%r unexpectedly found in %r' % (member, container)
696 self.fail(self._formatMessage(msg, standardMsg))
697
698 def assertIs(self, expr1, expr2, msg=None):
699 """Just like self.assertTrue(a is b), but with a nicer default message."""
700 if expr1 is not expr2:
701 standardMsg = '%r is not %r' % (expr1, expr2)
702 self.fail(self._formatMessage(msg, standardMsg))
703
704 def assertIsNot(self, expr1, expr2, msg=None):
705 """Just like self.assertTrue(a is not b), but with a nicer default message."""
706 if expr1 is expr2:
707 standardMsg = 'unexpectedly identical: %r' % (expr1,)
708 self.fail(self._formatMessage(msg, standardMsg))
709
710 def assertDictEqual(self, d1, d2, msg=None):
711 self.assert_(isinstance(d1, dict), 'First argument is not a dictionary')
712 self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary')
713
714 if d1 != d2:
715 standardMsg = ('\n' + '\n'.join(difflib.ndiff(
716 pprint.pformat(d1).splitlines(),
717 pprint.pformat(d2).splitlines())))
718 self.fail(self._formatMessage(msg, standardMsg))
719
720 def assertDictContainsSubset(self, expected, actual, msg=None):
721 """Checks whether actual is a superset of expected."""
722 missing = []
723 mismatched = []
724 for key, value in expected.items():
725 if key not in actual:
726 missing.append(key)
727 elif value != actual[key]:
728 mismatched.append('%s, expected: %s, actual: %s' % (key, value, actual[key]))
729
730 if not (missing or mismatched):
731 return
732
733 standardMsg = ''
734 if missing:
735 standardMsg = 'Missing: %r' % ','.join(missing)
736 if mismatched:
737 if standardMsg:
738 standardMsg += '; '
739 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
740
741 self.fail(self._formatMessage(msg, standardMsg))
742
743 def assertSameElements(self, expected_seq, actual_seq, msg=None):
744 """An unordered sequence specific comparison.
745
746 Raises with an error message listing which elements of expected_seq
747 are missing from actual_seq and vice versa if any.
748 """
749 try:
750 expected = set(expected_seq)
751 actual = set(actual_seq)
752 missing = list(expected.difference(actual))
753 unexpected = list(actual.difference(expected))
754 missing.sort()
755 unexpected.sort()
756 except TypeError:
757 # Fall back to slower list-compare if any of the objects are
758 # not hashable.
759 expected = list(expected_seq)
760 actual = list(actual_seq)
761 try:
762 expected.sort()
763 actual.sort()
764 except TypeError:
765 missing, unexpected = util.unorderable_list_difference(expected,
766 actual)
767 else:
768 missing, unexpected = util.sorted_list_difference(expected,
769 actual)
770 errors = []
771 if missing:
772 errors.append('Expected, but missing:\n %r' % missing)
773 if unexpected:
774 errors.append('Unexpected, but present:\n %r' % unexpected)
775 if errors:
776 standardMsg = '\n'.join(errors)
777 self.fail(self._formatMessage(msg, standardMsg))
778
779 def assertMultiLineEqual(self, first, second, msg=None):
780 """Assert that two multi-line strings are equal."""
781 self.assert_(isinstance(first, str), (
782 'First argument is not a string'))
783 self.assert_(isinstance(second, str), (
784 'Second argument is not a string'))
785
786 if first != second:
787 standardMsg = '\n' + ''.join(difflib.ndiff(first.splitlines(True), second.splitlines(True)))
788 self.fail(self._formatMessage(msg, standardMsg))
789
790 def assertLess(self, a, b, msg=None):
791 """Just like self.assertTrue(a < b), but with a nicer default message."""
792 if not a < b:
793 standardMsg = '%r not less than %r' % (a, b)
794 self.fail(self._formatMessage(msg, standardMsg))
795
796 def assertLessEqual(self, a, b, msg=None):
797 """Just like self.assertTrue(a <= b), but with a nicer default message."""
798 if not a <= b:
799 standardMsg = '%r not less than or equal to %r' % (a, b)
800 self.fail(self._formatMessage(msg, standardMsg))
801
802 def assertGreater(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 greater than %r' % (a, b)
806 self.fail(self._formatMessage(msg, standardMsg))
807
808 def assertGreaterEqual(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 greater than or equal to %r' % (a, b)
812 self.fail(self._formatMessage(msg, standardMsg))
813
814 def assertIsNone(self, obj, msg=None):
815 """Same as self.assertTrue(obj is None), with a nicer default message."""
816 if obj is not None:
817 standardMsg = '%r is not None' % obj
818 self.fail(self._formatMessage(msg, standardMsg))
819
820 def assertIsNotNone(self, obj, msg=None):
821 """Included for symmetry with assertIsNone."""
822 if obj is None:
823 standardMsg = 'unexpectedly None'
824 self.fail(self._formatMessage(msg, standardMsg))
825
826 def assertRaisesRegexp(self, expected_exception, expected_regexp,
827 callable_obj=None, *args, **kwargs):
828 """Asserts that the message in a raised exception matches a regexp.
829
830 Args:
831 expected_exception: Exception class expected to be raised.
832 expected_regexp: Regexp (re pattern object or string) expected
833 to be found in error message.
834 callable_obj: Function to be called.
835 args: Extra args.
836 kwargs: Extra kwargs.
837 """
838 context = _AssertRaisesContext(expected_exception, self, callable_obj,
839 expected_regexp)
840 if callable_obj is None:
841 return context
842 with context:
843 callable_obj(*args, **kwargs)
844
845 def assertRegexpMatches(self, text, expected_regex, msg=None):
846 if isinstance(expected_regex, (str, bytes)):
847 expected_regex = re.compile(expected_regex)
848 if not expected_regex.search(text):
849 msg = msg or "Regexp didn't match"
850 msg = '%s: %r not found in %r' % (msg, expected_regex.pattern, text)
851 raise self.failureException(msg)
852
853
854class FunctionTestCase(TestCase):
855 """A test case that wraps a test function.
856
857 This is useful for slipping pre-existing test functions into the
858 unittest framework. Optionally, set-up and tidy-up functions can be
859 supplied. As with TestCase, the tidy-up ('tearDown') function will
860 always be called if the set-up ('setUp') function ran successfully.
861 """
862
863 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
864 super(FunctionTestCase, self).__init__()
865 self._setUpFunc = setUp
866 self._tearDownFunc = tearDown
867 self._testFunc = testFunc
868 self._description = description
869
870 def setUp(self):
871 if self._setUpFunc is not None:
872 self._setUpFunc()
873
874 def tearDown(self):
875 if self._tearDownFunc is not None:
876 self._tearDownFunc()
877
878 def runTest(self):
879 self._testFunc()
880
881 def id(self):
882 return self._testFunc.__name__
883
884 def __eq__(self, other):
885 if not isinstance(other, self.__class__):
886 return NotImplemented
887
888 return self._setUpFunc == other._setUpFunc and \
889 self._tearDownFunc == other._tearDownFunc and \
890 self._testFunc == other._testFunc and \
891 self._description == other._description
892
893 def __ne__(self, other):
894 return not self == other
895
896 def __hash__(self):
897 return hash((type(self), self._setUpFunc, self._tearDownFunc,
898 self._testFunc, self._description))
899
900 def __str__(self):
901 return "%s (%s)" % (util.strclass(self.__class__),
902 self._testFunc.__name__)
903
904 def __repr__(self):
905 return "<%s testFunc=%s>" % (util.strclass(self.__class__),
906 self._testFunc)
907
908 def shortDescription(self):
909 if self._description is not None:
910 return self._description
911 doc = self._testFunc.__doc__
912 return doc and doc.split("\n")[0].strip() or None