1 """Test case implementation"""
10 from . import result
, util
13 class SkipTest(Exception):
15 Raise this exception in a test to skip it.
17 Usually you can use TestResult.skip() or one of the skipping decorators
18 instead of raising this directly.
22 class _ExpectedFailure(Exception):
24 Raise this when a test is expected to fail.
26 This is an implementation detail.
29 def __init__(self
, exc_info
):
30 super(_ExpectedFailure
, self
).__init
__()
31 self
.exc_info
= exc_info
33 class _UnexpectedSuccess(Exception):
35 The test was supposed to fail, but it didn't!
44 Unconditionally skip a test.
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
51 @functools.wraps(test_item
)
52 def skip_wrapper(*args
, **kwargs
):
53 raise SkipTest(reason
)
57 def skipIf(condition
, reason
):
59 Skip a test if the condition is true.
65 def skipUnless(condition
, reason
):
67 Skip a test unless the condition is true.
74 def expectedFailure(func
):
75 @functools.wraps(func
)
76 def wrapper(*args
, **kwargs
):
80 raise _ExpectedFailure(sys
.exc_info())
81 raise _UnexpectedSuccess
85 class _AssertRaisesContext(object):
86 """A context manager used to implement TestCase.assertRaises* methods."""
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
96 def __exit__(self
, exc_type
, exc_value
, tb
):
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
107 self
.exc_value
= exc_value
#store for later retrieval
108 if self
.expected_regex
is None:
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
)))
120 class TestCase(object):
121 """A class whose instances are single test cases.
123 By default, the test code itself should be placed in a method named
126 If the fixture may be used for many test cases, create as
127 many test methods as are needed. When instantiating such a TestCase
128 subclass, specify in the constructor arguments the name of the test method
129 that the instance is to execute.
131 Test authors should subclass TestCase for their own tests. Construction
132 and deconstruction of the test's environment ('fixture') can be
133 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
135 If it is necessary to override the __init__ method, the base class
136 __init__ method must always be called. It is important that subclasses
137 should not change the signature of their __init__ method, since instances
138 of the classes are instantiated automatically by parts of the framework
142 # This attribute determines which exception will be raised when
143 # the instance's assertion methods fail; test methods raising this
144 # exception will be deemed to have 'failed' rather than 'errored'
146 failureException
= AssertionError
148 # This attribute determines whether long messages (including repr of
149 # objects used in assert methods) will be printed on failure in *addition*
150 # to any explicit message passed.
155 def __init__(self
, methodName
='runTest'):
156 """Create an instance of the class that will use the named test
157 method when executed. Raises a ValueError if the instance does
158 not have a method with the specified name.
160 self
._testMethodName
= methodName
161 self
._resultForDoCleanups
= None
163 testMethod
= getattr(self
, methodName
)
164 except AttributeError:
165 raise ValueError("no such test method in %s: %s" % \
166 (self
.__class
__, methodName
))
167 self
._testMethodDoc
= testMethod
.__doc
__
170 # Map types to custom assertEqual functions that will compare
171 # instances of said type in more detail to generate a more useful
173 self
._type
_equality
_funcs
= {}
174 self
.addTypeEqualityFunc(dict, self
.assertDictEqual
)
175 self
.addTypeEqualityFunc(list, self
.assertListEqual
)
176 self
.addTypeEqualityFunc(tuple, self
.assertTupleEqual
)
177 self
.addTypeEqualityFunc(set, self
.assertSetEqual
)
178 self
.addTypeEqualityFunc(frozenset, self
.assertSetEqual
)
180 def addTypeEqualityFunc(self
, typeobj
, function
):
181 """Add a type specific assertEqual style function to compare a type.
183 This method is for use by TestCase subclasses that need to register
184 their own type equality functions to provide nicer error messages.
187 typeobj: The data type to call this function on when both values
188 are of the same type in assertEqual().
189 function: The callable taking two arguments and an optional
190 msg= argument that raises self.failureException with a
191 useful error message when the two arguments are not equal.
193 self
._type
_equality
_funcs
[typeobj
] = function
195 def addCleanup(self
, function
, *args
, **kwargs
):
196 """Add a function, with arguments, to be called when the test is
197 completed. Functions added are called on a LIFO basis and are
198 called after tearDown on test failure or success.
200 Cleanup items are called even if setUp fails (unlike tearDown)."""
201 self
._cleanups
.append((function
, args
, kwargs
))
204 "Hook method for setting up the test fixture before exercising it."
208 "Hook method for deconstructing the test fixture after testing it."
211 def countTestCases(self
):
214 def defaultTestResult(self
):
215 return result
.TestResult()
217 def shortDescription(self
):
218 """Returns both the test method name and first line of its docstring.
220 If no docstring is given, only returns the method name.
222 This method overrides unittest.TestCase.shortDescription(), which
223 only returns the first line of the docstring, obscuring the name
224 of the test upon failure.
227 doc_first_line
= None
229 if self
._testMethodDoc
:
230 doc_first_line
= self
._testMethodDoc
.split("\n")[0].strip()
232 desc
= '\n'.join((desc
, doc_first_line
))
236 return "%s.%s" % (util
.strclass(self
.__class
__), self
._testMethodName
)
238 def __eq__(self
, other
):
239 if type(self
) is not type(other
):
240 return NotImplemented
242 return self
._testMethodName
== other
._testMethodName
244 def __ne__(self
, other
):
245 return not self
== other
248 return hash((type(self
), self
._testMethodName
))
251 return "%s (%s)" % (self
._testMethodName
, util
.strclass(self
.__class
__))
254 return "<%s testMethod=%s>" % \
255 (util
.strclass(self
.__class
__), self
._testMethodName
)
257 def run(self
, result
=None):
260 result
= self
.defaultTestResult()
261 startTestRun
= getattr(result
, 'startTestRun', None)
262 if startTestRun
is not None:
265 self
._resultForDoCleanups
= result
266 result
.startTest(self
)
267 if getattr(self
.__class
__, "__unittest_skip__", False):
268 # If the whole class was skipped.
270 result
.addSkip(self
, self
.__class
__.__unittest
_skip
_why
__)
272 result
.stopTest(self
)
274 testMethod
= getattr(self
, self
._testMethodName
)
279 except SkipTest
as e
:
280 result
.addSkip(self
, str(e
))
282 result
.addError(self
, sys
.exc_info())
286 except self
.failureException
:
287 result
.addFailure(self
, sys
.exc_info())
288 except _ExpectedFailure
as e
:
289 result
.addExpectedFailure(self
, e
.exc_info
)
290 except _UnexpectedSuccess
:
291 result
.addUnexpectedSuccess(self
)
292 except SkipTest
as e
:
293 result
.addSkip(self
, str(e
))
295 result
.addError(self
, sys
.exc_info())
302 result
.addError(self
, sys
.exc_info())
305 cleanUpSuccess
= self
.doCleanups()
306 success
= success
and cleanUpSuccess
308 result
.addSuccess(self
)
310 result
.stopTest(self
)
311 if orig_result
is None:
312 stopTestRun
= getattr(result
, 'stopTestRun', None)
313 if stopTestRun
is not None:
316 def doCleanups(self
):
317 """Execute all cleanup functions. Normally called for you after
319 result
= self
._resultForDoCleanups
321 while self
._cleanups
:
322 function
, args
, kwargs
= self
._cleanups
.pop(-1)
324 function(*args
, **kwargs
)
327 result
.addError(self
, sys
.exc_info())
330 def __call__(self
, *args
, **kwds
):
331 return self
.run(*args
, **kwds
)
334 """Run the test without collecting errors in a TestResult"""
336 getattr(self
, self
._testMethodName
)()
339 def skipTest(self
, reason
):
340 """Skip this test."""
341 raise SkipTest(reason
)
343 def fail(self
, msg
=None):
344 """Fail immediately, with the given message."""
345 raise self
.failureException(msg
)
347 def assertFalse(self
, expr
, msg
=None):
348 "Fail the test if the expression is true."
350 msg
= self
._formatMessage
(msg
, "%r is not False" % expr
)
351 raise self
.failureException(msg
)
353 def assertTrue(self
, expr
, msg
=None):
354 """Fail the test unless the expression is true."""
356 msg
= self
._formatMessage
(msg
, "%r is not True" % expr
)
357 raise self
.failureException(msg
)
359 def _formatMessage(self
, msg
, standardMsg
):
360 """Honour the longMessage attribute when generating failure messages.
361 If longMessage is False this means:
362 * Use only an explicit message if it is provided
363 * Otherwise use the standard message for the assert
365 If longMessage is True:
366 * Use the standard message
367 * If an explicit message is provided, plus ' : ' and the explicit message
369 if not self
.longMessage
:
370 return msg
or standardMsg
373 return standardMsg
+ ' : ' + msg
376 def assertRaises(self
, excClass
, callableObj
=None, *args
, **kwargs
):
377 """Fail unless an exception of class excClass is thrown
378 by callableObj when invoked with arguments args and keyword
379 arguments kwargs. If a different type of exception is
380 thrown, it will not be caught, and the test case will be
381 deemed to have suffered an error, exactly as for an
382 unexpected exception.
384 If called with callableObj omitted or None, will return a
385 context object used like this::
387 with self.assertRaises(some_error_class):
390 context
= _AssertRaisesContext(excClass
, self
)
391 if callableObj
is None:
394 callableObj(*args
, **kwargs
)
396 def _getAssertEqualityFunc(self
, first
, second
):
397 """Get a detailed comparison function for the types of the two args.
399 Returns: A callable accepting (first, second, msg=None) that will
400 raise a failure exception if first != second with a useful human
401 readable error message for those types.
404 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
405 # and vice versa. I opted for the conservative approach in case
406 # subclasses are not intended to be compared in detail to their super
407 # class instances using a type equality func. This means testing
408 # subtypes won't automagically use the detailed comparison. Callers
409 # should use their type specific assertSpamEqual method to compare
410 # subclasses if the detailed comparison is desired and appropriate.
411 # See the discussion in http://bugs.python.org/issue2578.
413 if type(first
) is type(second
):
414 asserter
= self
._type
_equality
_funcs
.get(type(first
))
415 if asserter
is not None:
418 return self
._baseAssertEqual
420 def _baseAssertEqual(self
, first
, second
, msg
=None):
421 """The default assertEqual implementation, not type specific."""
422 if not first
== second
:
423 standardMsg
= '%r != %r' % (first
, second
)
424 msg
= self
._formatMessage
(msg
, standardMsg
)
425 raise self
.failureException(msg
)
427 def assertEqual(self
, first
, second
, msg
=None):
428 """Fail if the two objects are unequal as determined by the '=='
431 assertion_func
= self
._getAssertEqualityFunc
(first
, second
)
432 assertion_func(first
, second
, msg
=msg
)
434 def assertNotEqual(self
, first
, second
, msg
=None):
435 """Fail if the two objects are equal as determined by the '=='
438 if not first
!= second
:
439 msg
= self
._formatMessage
(msg
, '%r == %r' % (first
, second
))
440 raise self
.failureException(msg
)
442 def assertAlmostEqual(self
, first
, second
, places
=7, msg
=None):
443 """Fail if the two objects are unequal as determined by their
444 difference rounded to the given number of decimal places
445 (default 7) and comparing to zero.
447 Note that decimal places (from zero) are usually not the same
448 as significant digits (measured from the most signficant digit).
450 If the two objects compare equal then they will automatically
451 compare almost equal.
456 if round(abs(second
-first
), places
) != 0:
457 standardMsg
= '%r != %r within %r places' % (first
, second
, places
)
458 msg
= self
._formatMessage
(msg
, standardMsg
)
459 raise self
.failureException(msg
)
461 def assertNotAlmostEqual(self
, first
, second
, places
=7, msg
=None):
462 """Fail if the two objects are equal as determined by their
463 difference rounded to the given number of decimal places
464 (default 7) and comparing to zero.
466 Note that decimal places (from zero) are usually not the same
467 as significant digits (measured from the most signficant digit).
469 Objects that are equal automatically fail.
471 if (first
== second
) or round(abs(second
-first
), places
) == 0:
472 standardMsg
= '%r == %r within %r places' % (first
, second
, places
)
473 msg
= self
._formatMessage
(msg
, standardMsg
)
474 raise self
.failureException(msg
)
476 # Synonyms for assertion methods
478 # The plurals are undocumented. Keep them that way to discourage use.
479 # Do not add more. Do not remove.
480 # Going through a deprecation cycle on these would annoy many people.
481 assertEquals
= assertEqual
482 assertNotEquals
= assertNotEqual
483 assertAlmostEquals
= assertAlmostEqual
484 assertNotAlmostEquals
= assertNotAlmostEqual
487 # These fail* assertion method names are pending deprecation and will
488 # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
489 def _deprecate(original_func
):
490 def deprecated_func(*args
, **kwargs
):
492 'Please use {0} instead.'.format(original_func
.__name
__),
493 PendingDeprecationWarning
, 2)
494 return original_func(*args
, **kwargs
)
495 return deprecated_func
497 failUnlessEqual
= _deprecate(assertEqual
)
498 failIfEqual
= _deprecate(assertNotEqual
)
499 failUnlessAlmostEqual
= _deprecate(assertAlmostEqual
)
500 failIfAlmostEqual
= _deprecate(assertNotAlmostEqual
)
501 failUnless
= _deprecate(assertTrue
)
502 failUnlessRaises
= _deprecate(assertRaises
)
503 failIf
= _deprecate(assertFalse
)
505 def assertSequenceEqual(self
, seq1
, seq2
, msg
=None, seq_type
=None):
506 """An equality assertion for ordered sequences (like lists and tuples).
508 For the purposes of this function, a valid orderd sequence type is one
509 which can be indexed, has a length, and has an equality operator.
512 seq1: The first sequence to compare.
513 seq2: The second sequence to compare.
514 seq_type: The expected datatype of the sequences, or None if no
515 datatype should be enforced.
516 msg: Optional message to use on failure instead of a list of
520 seq_type_name
= seq_type
.__name
__
521 if not isinstance(seq1
, seq_type
):
522 raise self
.failureException('First sequence is not a %s: %r'
523 % (seq_type_name
, seq1
))
524 if not isinstance(seq2
, seq_type
):
525 raise self
.failureException('Second sequence is not a %s: %r'
526 % (seq_type_name
, seq2
))
528 seq_type_name
= "sequence"
533 except (TypeError, NotImplementedError):
534 differing
= 'First %s has no length. Non-sequence?' % (
537 if differing
is None:
540 except (TypeError, NotImplementedError):
541 differing
= 'Second %s has no length. Non-sequence?' % (
544 if differing
is None:
548 seq1_repr
= repr(seq1
)
549 seq2_repr
= repr(seq2
)
550 if len(seq1_repr
) > 30:
551 seq1_repr
= seq1_repr
[:30] + '...'
552 if len(seq2_repr
) > 30:
553 seq2_repr
= seq2_repr
[:30] + '...'
554 elements
= (seq_type_name
.capitalize(), seq1_repr
, seq2_repr
)
555 differing
= '%ss differ: %s != %s\n' % elements
557 for i
in xrange(min(len1
, len2
)):
560 except (TypeError, IndexError, NotImplementedError):
561 differing
+= ('\nUnable to index element %d of first %s\n' %
567 except (TypeError, IndexError, NotImplementedError):
568 differing
+= ('\nUnable to index element %d of second %s\n' %
573 differing
+= ('\nFirst differing element %d:\n%s\n%s\n' %
577 if (len1
== len2
and seq_type
is None and
578 type(seq1
) != type(seq2
)):
579 # The sequences are the same, but have differing types.
583 differing
+= ('\nFirst %s contains %d additional '
584 'elements.\n' % (seq_type_name
, len1
- len2
))
586 differing
+= ('First extra element %d:\n%s\n' %
588 except (TypeError, IndexError, NotImplementedError):
589 differing
+= ('Unable to index element %d '
590 'of first %s\n' % (len2
, seq_type_name
))
592 differing
+= ('\nSecond %s contains %d additional '
593 'elements.\n' % (seq_type_name
, len2
- len1
))
595 differing
+= ('First extra element %d:\n%s\n' %
597 except (TypeError, IndexError, NotImplementedError):
598 differing
+= ('Unable to index element %d '
599 'of second %s\n' % (len1
, seq_type_name
))
600 standardMsg
= differing
+ '\n' + '\n'.join(
601 difflib
.ndiff(pprint
.pformat(seq1
).splitlines(),
602 pprint
.pformat(seq2
).splitlines()))
603 msg
= self
._formatMessage
(msg
, standardMsg
)
606 def assertListEqual(self
, list1
, list2
, msg
=None):
607 """A list-specific equality assertion.
610 list1: The first list to compare.
611 list2: The second list to compare.
612 msg: Optional message to use on failure instead of a list of
616 self
.assertSequenceEqual(list1
, list2
, msg
, seq_type
=list)
618 def assertTupleEqual(self
, tuple1
, tuple2
, msg
=None):
619 """A tuple-specific equality assertion.
622 tuple1: The first tuple to compare.
623 tuple2: The second tuple to compare.
624 msg: Optional message to use on failure instead of a list of
627 self
.assertSequenceEqual(tuple1
, tuple2
, msg
, seq_type
=tuple)
629 def assertSetEqual(self
, set1
, set2
, msg
=None):
630 """A set-specific equality assertion.
633 set1: The first set to compare.
634 set2: The second set to compare.
635 msg: Optional message to use on failure instead of a list of
638 For more general containership equality, assertSameElements will work
639 with things other than sets. This uses ducktyping to support
640 different types of sets, and is optimized for sets specifically
641 (parameters must support a difference method).
644 difference1
= set1
.difference(set2
)
646 self
.fail('invalid type when attempting set difference: %s' % e
)
647 except AttributeError, e
:
648 self
.fail('first argument does not support set difference: %s' % e
)
651 difference2
= set2
.difference(set1
)
653 self
.fail('invalid type when attempting set difference: %s' % e
)
654 except AttributeError, e
:
655 self
.fail('second argument does not support set difference: %s' % e
)
657 if not (difference1
or difference2
):
662 lines
.append('Items in the first set but not the second:')
663 for item
in difference1
:
664 lines
.append(repr(item
))
666 lines
.append('Items in the second set but not the first:')
667 for item
in difference2
:
668 lines
.append(repr(item
))
670 standardMsg
= '\n'.join(lines
)
671 self
.fail(self
._formatMessage
(msg
, standardMsg
))
673 def assertIn(self
, member
, container
, msg
=None):
674 """Just like self.assertTrue(a in b), but with a nicer default message."""
675 if member
not in container
:
676 standardMsg
= '%r not found in %r' % (member
, container
)
677 self
.fail(self
._formatMessage
(msg
, standardMsg
))
679 def assertNotIn(self
, member
, container
, msg
=None):
680 """Just like self.assertTrue(a not in b), but with a nicer default message."""
681 if member
in container
:
682 standardMsg
= '%r unexpectedly found in %r' % (member
, container
)
683 self
.fail(self
._formatMessage
(msg
, standardMsg
))
685 def assertIs(self
, expr1
, expr2
, msg
=None):
686 """Just like self.assertTrue(a is b), but with a nicer default message."""
687 if expr1
is not expr2
:
688 standardMsg
= '%r is not %r' % (expr1
, expr2
)
689 self
.fail(self
._formatMessage
(msg
, standardMsg
))
691 def assertIsNot(self
, expr1
, expr2
, msg
=None):
692 """Just like self.assertTrue(a is not b), but with a nicer default message."""
694 standardMsg
= 'unexpectedly identical: %r' % (expr1
,)
695 self
.fail(self
._formatMessage
(msg
, standardMsg
))
697 def assertDictEqual(self
, d1
, d2
, msg
=None):
698 self
.assert_(isinstance(d1
, dict), 'First argument is not a dictionary')
699 self
.assert_(isinstance(d2
, dict), 'Second argument is not a dictionary')
702 standardMsg
= ('\n' + '\n'.join(difflib
.ndiff(
703 pprint
.pformat(d1
).splitlines(),
704 pprint
.pformat(d2
).splitlines())))
705 self
.fail(self
._formatMessage
(msg
, standardMsg
))
707 def assertDictContainsSubset(self
, expected
, actual
, msg
=None):
708 """Checks whether actual is a superset of expected."""
711 for key
, value
in expected
.iteritems():
712 if key
not in actual
:
714 elif value
!= actual
[key
]:
715 mismatched
.append('%s, expected: %s, actual: %s' %
716 (key
, value
, actual
[key
]))
718 if not (missing
or mismatched
):
723 standardMsg
= 'Missing: %r' % ','.join(missing
)
727 standardMsg
+= 'Mismatched values: %s' % ','.join(mismatched
)
729 self
.fail(self
._formatMessage
(msg
, standardMsg
))
731 def assertSameElements(self
, expected_seq
, actual_seq
, msg
=None):
732 """An unordered sequence specific comparison.
734 Raises with an error message listing which elements of expected_seq
735 are missing from actual_seq and vice versa if any.
738 expected
= set(expected_seq
)
739 actual
= set(actual_seq
)
740 missing
= list(expected
.difference(actual
))
741 unexpected
= list(actual
.difference(expected
))
745 # Fall back to slower list-compare if any of the objects are
747 expected
= list(expected_seq
)
748 actual
= list(actual_seq
)
751 missing
, unexpected
= util
.sorted_list_difference(expected
, actual
)
754 errors
.append('Expected, but missing:\n %r' % missing
)
756 errors
.append('Unexpected, but present:\n %r' % unexpected
)
758 standardMsg
= '\n'.join(errors
)
759 self
.fail(self
._formatMessage
(msg
, standardMsg
))
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'))
769 standardMsg
= '\n' + ''.join(difflib
.ndiff(first
.splitlines(True),
770 second
.splitlines(True)))
771 self
.fail(self
._formatMessage
(msg
, standardMsg
))
773 def assertLess(self
, a
, b
, msg
=None):
774 """Just like self.assertTrue(a < b), but with a nicer default message."""
776 standardMsg
= '%r not less than %r' % (a
, b
)
777 self
.fail(self
._formatMessage
(msg
, standardMsg
))
779 def assertLessEqual(self
, a
, b
, msg
=None):
780 """Just like self.assertTrue(a <= b), but with a nicer default message."""
782 standardMsg
= '%r not less than or equal to %r' % (a
, b
)
783 self
.fail(self
._formatMessage
(msg
, standardMsg
))
785 def assertGreater(self
, a
, b
, msg
=None):
786 """Just like self.assertTrue(a > b), but with a nicer default message."""
788 standardMsg
= '%r not greater than %r' % (a
, b
)
789 self
.fail(self
._formatMessage
(msg
, standardMsg
))
791 def assertGreaterEqual(self
, a
, b
, msg
=None):
792 """Just like self.assertTrue(a >= b), but with a nicer default message."""
794 standardMsg
= '%r not greater than or equal to %r' % (a
, b
)
795 self
.fail(self
._formatMessage
(msg
, standardMsg
))
797 def assertIsNone(self
, obj
, msg
=None):
798 """Same as self.assertTrue(obj is None), with a nicer default message."""
800 standardMsg
= '%r is not None' % obj
801 self
.fail(self
._formatMessage
(msg
, standardMsg
))
803 def assertIsNotNone(self
, obj
, msg
=None):
804 """Included for symmetry with assertIsNone."""
806 standardMsg
= 'unexpectedly None'
807 self
.fail(self
._formatMessage
(msg
, standardMsg
))
809 def assertIsInstance(self
, obj
, cls
, msg
=None):
810 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
812 if not isinstance(obj
, cls
):
813 standardMsg
= '%r is not an instance of %r' % (obj
, cls
)
814 self
.fail(self
._formatMessage
(msg
, standardMsg
))
816 def assertNotIsInstance(self
, obj
, cls
, msg
=None):
817 """Included for symmetry with assertIsInstance."""
818 if isinstance(obj
, cls
):
819 standardMsg
= '%r is an instance of %r' % (obj
, cls
)
820 self
.fail(self
._formatMessage
(msg
, standardMsg
))
822 def assertRaisesRegexp(self
, expected_exception
, expected_regexp
,
823 callable_obj
=None, *args
, **kwargs
):
824 """Asserts that the message in a raised exception matches a regexp.
827 expected_exception: Exception class expected to be raised.
828 expected_regexp: Regexp (re pattern object or string) expected
829 to be found in error message.
830 callable_obj: Function to be called.
832 kwargs: Extra kwargs.
834 context
= _AssertRaisesContext(expected_exception
, self
, expected_regexp
)
835 if callable_obj
is None:
838 callable_obj(*args
, **kwargs
)
840 def assertRegexpMatches(self
, text
, expected_regex
, msg
=None):
841 if isinstance(expected_regex
, basestring
):
842 expected_regex
= re
.compile(expected_regex
)
843 if not expected_regex
.search(text
):
844 msg
= msg
or "Regexp didn't match"
845 msg
= '%s: %r not found in %r' % (msg
, expected_regex
.pattern
, text
)
846 raise self
.failureException(msg
)
849 class FunctionTestCase(TestCase
):
850 """A test case that wraps a test function.
852 This is useful for slipping pre-existing test functions into the
853 unittest framework. Optionally, set-up and tidy-up functions can be
854 supplied. As with TestCase, the tidy-up ('tearDown') function will
855 always be called if the set-up ('setUp') function ran successfully.
858 def __init__(self
, testFunc
, setUp
=None, tearDown
=None, description
=None):
859 super(FunctionTestCase
, self
).__init
__()
860 self
._setUpFunc
= setUp
861 self
._tearDownFunc
= tearDown
862 self
._testFunc
= testFunc
863 self
._description
= description
866 if self
._setUpFunc
is not None:
870 if self
._tearDownFunc
is not None:
877 return self
._testFunc
.__name
__
879 def __eq__(self
, other
):
880 if not isinstance(other
, self
.__class
__):
881 return NotImplemented
883 return self
._setUpFunc
== other
._setUpFunc
and \
884 self
._tearDownFunc
== other
._tearDownFunc
and \
885 self
._testFunc
== other
._testFunc
and \
886 self
._description
== other
._description
888 def __ne__(self
, other
):
889 return not self
== other
892 return hash((type(self
), self
._setUpFunc
, self
._tearDownFunc
,
893 self
._testFunc
, self
._description
))
896 return "%s (%s)" % (util
.strclass(self
.__class
__),
897 self
._testFunc
.__name
__)
900 return "<%s testFunc=%s>" % (util
.strclass(self
.__class
__),
903 def shortDescription(self
):
904 if self
._description
is not None:
905 return self
._description
906 doc
= self
._testFunc
.__doc
__
907 return doc
and doc
.split("\n")[0].strip() or None