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