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