blob: e8ebc90d61f37a928e715dde43265ed99c5604cb [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
Georg Brandlb0eb4d32010-02-07 11:34:15 +000091 self.expected_regexp = expected_regexp
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +000092
93 def __enter__(self):
Michael Foord2bd52dc2010-02-07 18:44:12 +000094 return self
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +000095
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
Georg Brandldc3694b2010-02-07 17:02:22 +0000107 self.exception = exc_value # store for later retrieval
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000108 if self.expected_regexp is None:
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000109 return True
110
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000111 expected_regexp = self.expected_regexp
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000112 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
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000120class TestCase(object):
121 """A class whose instances are single test cases.
122
123 By default, the test code itself should be placed in a method named
124 'runTest'.
125
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.
130
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.
134
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
139 in order to be run.
140 """
141
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'
145
146 failureException = AssertionError
147
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.
151
152 longMessage = False
153
154
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.
159 """
160 self._testMethodName = methodName
161 self._resultForDoCleanups = None
162 try:
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__
168 self._cleanups = []
169
170 # Map types to custom assertEqual functions that will compare
171 # instances of said type in more detail to generate a more useful
172 # error message.
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)
Michael Foordfe6349c2010-02-08 22:41:16 +0000179 self.addTypeEqualityFunc(unicode, self.assertMultiLineEqual)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000180
181 def addTypeEqualityFunc(self, typeobj, function):
182 """Add a type specific assertEqual style function to compare a type.
183
184 This method is for use by TestCase subclasses that need to register
185 their own type equality functions to provide nicer error messages.
186
187 Args:
188 typeobj: The data type to call this function on when both values
189 are of the same type in assertEqual().
190 function: The callable taking two arguments and an optional
191 msg= argument that raises self.failureException with a
192 useful error message when the two arguments are not equal.
193 """
Benjamin Petersond46430b2009-11-29 22:26:26 +0000194 self._type_equality_funcs[typeobj] = function
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000195
196 def addCleanup(self, function, *args, **kwargs):
197 """Add a function, with arguments, to be called when the test is
198 completed. Functions added are called on a LIFO basis and are
199 called after tearDown on test failure or success.
200
201 Cleanup items are called even if setUp fails (unlike tearDown)."""
202 self._cleanups.append((function, args, kwargs))
203
204 def setUp(self):
205 "Hook method for setting up the test fixture before exercising it."
206 pass
207
208 def tearDown(self):
209 "Hook method for deconstructing the test fixture after testing it."
210 pass
211
212 def countTestCases(self):
213 return 1
214
215 def defaultTestResult(self):
216 return result.TestResult()
217
218 def shortDescription(self):
219 """Returns both the test method name and first line of its docstring.
220
221 If no docstring is given, only returns the method name.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000222 """
223 desc = str(self)
224 doc_first_line = None
225
226 if self._testMethodDoc:
227 doc_first_line = self._testMethodDoc.split("\n")[0].strip()
228 if doc_first_line:
229 desc = '\n'.join((desc, doc_first_line))
230 return desc
231
232 def id(self):
233 return "%s.%s" % (util.strclass(self.__class__), self._testMethodName)
234
235 def __eq__(self, other):
236 if type(self) is not type(other):
237 return NotImplemented
238
239 return self._testMethodName == other._testMethodName
240
241 def __ne__(self, other):
242 return not self == other
243
244 def __hash__(self):
245 return hash((type(self), self._testMethodName))
246
247 def __str__(self):
248 return "%s (%s)" % (self._testMethodName, util.strclass(self.__class__))
249
250 def __repr__(self):
251 return "<%s testMethod=%s>" % \
252 (util.strclass(self.__class__), self._testMethodName)
253
254 def run(self, result=None):
255 orig_result = result
256 if result is None:
257 result = self.defaultTestResult()
258 startTestRun = getattr(result, 'startTestRun', None)
259 if startTestRun is not None:
260 startTestRun()
261
262 self._resultForDoCleanups = result
263 result.startTest(self)
264 if getattr(self.__class__, "__unittest_skip__", False):
265 # If the whole class was skipped.
266 try:
267 result.addSkip(self, self.__class__.__unittest_skip_why__)
268 finally:
269 result.stopTest(self)
270 return
271 testMethod = getattr(self, self._testMethodName)
272 try:
273 success = False
274 try:
275 self.setUp()
276 except SkipTest as e:
277 result.addSkip(self, str(e))
278 except Exception:
279 result.addError(self, sys.exc_info())
280 else:
281 try:
282 testMethod()
283 except self.failureException:
284 result.addFailure(self, sys.exc_info())
285 except _ExpectedFailure as e:
286 result.addExpectedFailure(self, e.exc_info)
287 except _UnexpectedSuccess:
288 result.addUnexpectedSuccess(self)
289 except SkipTest as e:
290 result.addSkip(self, str(e))
291 except Exception:
292 result.addError(self, sys.exc_info())
293 else:
294 success = True
295
296 try:
297 self.tearDown()
298 except Exception:
299 result.addError(self, sys.exc_info())
300 success = False
301
302 cleanUpSuccess = self.doCleanups()
303 success = success and cleanUpSuccess
304 if success:
305 result.addSuccess(self)
306 finally:
307 result.stopTest(self)
308 if orig_result is None:
309 stopTestRun = getattr(result, 'stopTestRun', None)
310 if stopTestRun is not None:
311 stopTestRun()
312
313 def doCleanups(self):
314 """Execute all cleanup functions. Normally called for you after
315 tearDown."""
316 result = self._resultForDoCleanups
317 ok = True
318 while self._cleanups:
319 function, args, kwargs = self._cleanups.pop(-1)
320 try:
321 function(*args, **kwargs)
322 except Exception:
323 ok = False
324 result.addError(self, sys.exc_info())
325 return ok
326
327 def __call__(self, *args, **kwds):
328 return self.run(*args, **kwds)
329
330 def debug(self):
331 """Run the test without collecting errors in a TestResult"""
332 self.setUp()
333 getattr(self, self._testMethodName)()
334 self.tearDown()
335
336 def skipTest(self, reason):
337 """Skip this test."""
338 raise SkipTest(reason)
339
340 def fail(self, msg=None):
341 """Fail immediately, with the given message."""
342 raise self.failureException(msg)
343
344 def assertFalse(self, expr, msg=None):
345 "Fail the test if the expression is true."
346 if expr:
347 msg = self._formatMessage(msg, "%r is not False" % expr)
348 raise self.failureException(msg)
349
350 def assertTrue(self, expr, msg=None):
351 """Fail the test unless the expression is true."""
352 if not expr:
353 msg = self._formatMessage(msg, "%r is not True" % expr)
354 raise self.failureException(msg)
355
356 def _formatMessage(self, msg, standardMsg):
357 """Honour the longMessage attribute when generating failure messages.
358 If longMessage is False this means:
359 * Use only an explicit message if it is provided
360 * Otherwise use the standard message for the assert
361
362 If longMessage is True:
363 * Use the standard message
364 * If an explicit message is provided, plus ' : ' and the explicit message
365 """
366 if not self.longMessage:
367 return msg or standardMsg
368 if msg is None:
369 return standardMsg
370 return standardMsg + ' : ' + msg
371
372
373 def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
374 """Fail unless an exception of class excClass is thrown
375 by callableObj when invoked with arguments args and keyword
376 arguments kwargs. If a different type of exception is
377 thrown, it will not be caught, and the test case will be
378 deemed to have suffered an error, exactly as for an
379 unexpected exception.
380
381 If called with callableObj omitted or None, will return a
382 context object used like this::
383
Michael Foordd0edec32010-02-05 22:55:09 +0000384 with self.assertRaises(SomeException):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000385 do_something()
Michael Foordd0edec32010-02-05 22:55:09 +0000386
387 The context manager keeps a reference to the exception as
Ezio Melotticd4f6572010-02-08 21:52:08 +0000388 the 'exception' attribute. This allows you to inspect the
Michael Foordd0edec32010-02-05 22:55:09 +0000389 exception after the assertion::
390
391 with self.assertRaises(SomeException) as cm:
392 do_something()
Georg Brandldc3694b2010-02-07 17:02:22 +0000393 the_exception = cm.exception
Michael Foord757cc4d2010-02-05 23:22:37 +0000394 self.assertEqual(the_exception.error_code, 3)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000395 """
396 context = _AssertRaisesContext(excClass, self)
397 if callableObj is None:
398 return context
399 with context:
400 callableObj(*args, **kwargs)
401
402 def _getAssertEqualityFunc(self, first, second):
403 """Get a detailed comparison function for the types of the two args.
404
405 Returns: A callable accepting (first, second, msg=None) that will
406 raise a failure exception if first != second with a useful human
407 readable error message for those types.
408 """
409 #
410 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
411 # and vice versa. I opted for the conservative approach in case
412 # subclasses are not intended to be compared in detail to their super
413 # class instances using a type equality func. This means testing
414 # subtypes won't automagically use the detailed comparison. Callers
415 # should use their type specific assertSpamEqual method to compare
416 # subclasses if the detailed comparison is desired and appropriate.
417 # See the discussion in http://bugs.python.org/issue2578.
418 #
419 if type(first) is type(second):
420 asserter = self._type_equality_funcs.get(type(first))
421 if asserter is not None:
Benjamin Petersond46430b2009-11-29 22:26:26 +0000422 return asserter
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000423
424 return self._baseAssertEqual
425
426 def _baseAssertEqual(self, first, second, msg=None):
427 """The default assertEqual implementation, not type specific."""
428 if not first == second:
429 standardMsg = '%r != %r' % (first, second)
430 msg = self._formatMessage(msg, standardMsg)
431 raise self.failureException(msg)
432
433 def assertEqual(self, first, second, msg=None):
434 """Fail if the two objects are unequal as determined by the '=='
435 operator.
436 """
437 assertion_func = self._getAssertEqualityFunc(first, second)
438 assertion_func(first, second, msg=msg)
439
440 def assertNotEqual(self, first, second, msg=None):
441 """Fail if the two objects are equal as determined by the '=='
442 operator.
443 """
444 if not first != second:
445 msg = self._formatMessage(msg, '%r == %r' % (first, second))
446 raise self.failureException(msg)
447
448 def assertAlmostEqual(self, first, second, places=7, msg=None):
449 """Fail if the two objects are unequal as determined by their
450 difference rounded to the given number of decimal places
451 (default 7) and comparing to zero.
452
453 Note that decimal places (from zero) are usually not the same
454 as significant digits (measured from the most signficant digit).
Michael Foordc3f79372009-09-13 16:40:02 +0000455
456 If the two objects compare equal then they will automatically
457 compare almost equal.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000458 """
Michael Foordc3f79372009-09-13 16:40:02 +0000459 if first == second:
460 # shortcut for ite
461 return
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000462 if round(abs(second-first), places) != 0:
463 standardMsg = '%r != %r within %r places' % (first, second, places)
464 msg = self._formatMessage(msg, standardMsg)
465 raise self.failureException(msg)
466
467 def assertNotAlmostEqual(self, first, second, places=7, msg=None):
468 """Fail if the two objects are equal as determined by their
469 difference rounded to the given number of decimal places
470 (default 7) and comparing to zero.
471
472 Note that decimal places (from zero) are usually not the same
473 as significant digits (measured from the most signficant digit).
Michael Foordc3f79372009-09-13 16:40:02 +0000474
475 Objects that are equal automatically fail.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000476 """
Michael Foordc3f79372009-09-13 16:40:02 +0000477 if (first == second) or round(abs(second-first), places) == 0:
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000478 standardMsg = '%r == %r within %r places' % (first, second, places)
479 msg = self._formatMessage(msg, standardMsg)
480 raise self.failureException(msg)
481
482 # Synonyms for assertion methods
483
484 # The plurals are undocumented. Keep them that way to discourage use.
485 # Do not add more. Do not remove.
486 # Going through a deprecation cycle on these would annoy many people.
487 assertEquals = assertEqual
488 assertNotEquals = assertNotEqual
489 assertAlmostEquals = assertAlmostEqual
490 assertNotAlmostEquals = assertNotAlmostEqual
491 assert_ = assertTrue
492
493 # These fail* assertion method names are pending deprecation and will
494 # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
495 def _deprecate(original_func):
496 def deprecated_func(*args, **kwargs):
497 warnings.warn(
498 'Please use {0} instead.'.format(original_func.__name__),
499 PendingDeprecationWarning, 2)
500 return original_func(*args, **kwargs)
501 return deprecated_func
502
503 failUnlessEqual = _deprecate(assertEqual)
504 failIfEqual = _deprecate(assertNotEqual)
505 failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
506 failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
507 failUnless = _deprecate(assertTrue)
508 failUnlessRaises = _deprecate(assertRaises)
509 failIf = _deprecate(assertFalse)
510
511 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
512 """An equality assertion for ordered sequences (like lists and tuples).
513
R. David Murray05b41712010-01-29 19:35:39 +0000514 For the purposes of this function, a valid ordered sequence type is one
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000515 which can be indexed, has a length, and has an equality operator.
516
517 Args:
518 seq1: The first sequence to compare.
519 seq2: The second sequence to compare.
520 seq_type: The expected datatype of the sequences, or None if no
521 datatype should be enforced.
522 msg: Optional message to use on failure instead of a list of
523 differences.
524 """
525 if seq_type != None:
526 seq_type_name = seq_type.__name__
527 if not isinstance(seq1, seq_type):
528 raise self.failureException('First sequence is not a %s: %r'
529 % (seq_type_name, seq1))
530 if not isinstance(seq2, seq_type):
531 raise self.failureException('Second sequence is not a %s: %r'
532 % (seq_type_name, seq2))
533 else:
534 seq_type_name = "sequence"
535
536 differing = None
537 try:
538 len1 = len(seq1)
539 except (TypeError, NotImplementedError):
540 differing = 'First %s has no length. Non-sequence?' % (
541 seq_type_name)
542
543 if differing is None:
544 try:
545 len2 = len(seq2)
546 except (TypeError, NotImplementedError):
547 differing = 'Second %s has no length. Non-sequence?' % (
548 seq_type_name)
549
550 if differing is None:
551 if seq1 == seq2:
552 return
553
554 seq1_repr = repr(seq1)
555 seq2_repr = repr(seq2)
556 if len(seq1_repr) > 30:
557 seq1_repr = seq1_repr[:30] + '...'
558 if len(seq2_repr) > 30:
559 seq2_repr = seq2_repr[:30] + '...'
560 elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
561 differing = '%ss differ: %s != %s\n' % elements
562
563 for i in xrange(min(len1, len2)):
564 try:
565 item1 = seq1[i]
566 except (TypeError, IndexError, NotImplementedError):
567 differing += ('\nUnable to index element %d of first %s\n' %
568 (i, seq_type_name))
569 break
570
571 try:
572 item2 = seq2[i]
573 except (TypeError, IndexError, NotImplementedError):
574 differing += ('\nUnable to index element %d of second %s\n' %
575 (i, seq_type_name))
576 break
577
578 if item1 != item2:
579 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
580 (i, item1, item2))
581 break
582 else:
583 if (len1 == len2 and seq_type is None and
584 type(seq1) != type(seq2)):
585 # The sequences are the same, but have differing types.
586 return
587
588 if len1 > len2:
589 differing += ('\nFirst %s contains %d additional '
590 'elements.\n' % (seq_type_name, len1 - len2))
591 try:
592 differing += ('First extra element %d:\n%s\n' %
593 (len2, seq1[len2]))
594 except (TypeError, IndexError, NotImplementedError):
595 differing += ('Unable to index element %d '
596 'of first %s\n' % (len2, seq_type_name))
597 elif len1 < len2:
598 differing += ('\nSecond %s contains %d additional '
599 'elements.\n' % (seq_type_name, len2 - len1))
600 try:
601 differing += ('First extra element %d:\n%s\n' %
602 (len1, seq2[len1]))
603 except (TypeError, IndexError, NotImplementedError):
604 differing += ('Unable to index element %d '
605 'of second %s\n' % (len1, seq_type_name))
Georg Brandl46cc46a2009-10-01 20:11:14 +0000606 standardMsg = differing + '\n' + '\n'.join(
607 difflib.ndiff(pprint.pformat(seq1).splitlines(),
608 pprint.pformat(seq2).splitlines()))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000609 msg = self._formatMessage(msg, standardMsg)
610 self.fail(msg)
611
612 def assertListEqual(self, list1, list2, msg=None):
613 """A list-specific equality assertion.
614
615 Args:
616 list1: The first list to compare.
617 list2: The second list to compare.
618 msg: Optional message to use on failure instead of a list of
619 differences.
620
621 """
622 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
623
624 def assertTupleEqual(self, tuple1, tuple2, msg=None):
625 """A tuple-specific equality assertion.
626
627 Args:
628 tuple1: The first tuple to compare.
629 tuple2: The second tuple to compare.
630 msg: Optional message to use on failure instead of a list of
631 differences.
632 """
633 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
634
635 def assertSetEqual(self, set1, set2, msg=None):
636 """A set-specific equality assertion.
637
638 Args:
639 set1: The first set to compare.
640 set2: The second set to compare.
641 msg: Optional message to use on failure instead of a list of
642 differences.
643
644 For more general containership equality, assertSameElements will work
645 with things other than sets. This uses ducktyping to support
646 different types of sets, and is optimized for sets specifically
647 (parameters must support a difference method).
648 """
649 try:
650 difference1 = set1.difference(set2)
651 except TypeError, e:
652 self.fail('invalid type when attempting set difference: %s' % e)
653 except AttributeError, e:
654 self.fail('first argument does not support set difference: %s' % e)
655
656 try:
657 difference2 = set2.difference(set1)
658 except TypeError, e:
659 self.fail('invalid type when attempting set difference: %s' % e)
660 except AttributeError, e:
661 self.fail('second argument does not support set difference: %s' % e)
662
663 if not (difference1 or difference2):
664 return
665
666 lines = []
667 if difference1:
668 lines.append('Items in the first set but not the second:')
669 for item in difference1:
670 lines.append(repr(item))
671 if difference2:
672 lines.append('Items in the second set but not the first:')
673 for item in difference2:
674 lines.append(repr(item))
675
676 standardMsg = '\n'.join(lines)
677 self.fail(self._formatMessage(msg, standardMsg))
678
679 def assertIn(self, member, container, msg=None):
680 """Just like self.assertTrue(a in b), but with a nicer default message."""
681 if member not in container:
682 standardMsg = '%r not found in %r' % (member, container)
683 self.fail(self._formatMessage(msg, standardMsg))
684
685 def assertNotIn(self, member, container, msg=None):
686 """Just like self.assertTrue(a not in b), but with a nicer default message."""
687 if member in container:
688 standardMsg = '%r unexpectedly found in %r' % (member, container)
689 self.fail(self._formatMessage(msg, standardMsg))
690
691 def assertIs(self, expr1, expr2, msg=None):
692 """Just like self.assertTrue(a is b), but with a nicer default message."""
693 if expr1 is not expr2:
694 standardMsg = '%r is not %r' % (expr1, expr2)
695 self.fail(self._formatMessage(msg, standardMsg))
696
697 def assertIsNot(self, expr1, expr2, msg=None):
698 """Just like self.assertTrue(a is not b), but with a nicer default message."""
699 if expr1 is expr2:
700 standardMsg = 'unexpectedly identical: %r' % (expr1,)
701 self.fail(self._formatMessage(msg, standardMsg))
702
703 def assertDictEqual(self, d1, d2, msg=None):
704 self.assert_(isinstance(d1, dict), 'First argument is not a dictionary')
705 self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary')
706
707 if d1 != d2:
708 standardMsg = ('\n' + '\n'.join(difflib.ndiff(
709 pprint.pformat(d1).splitlines(),
710 pprint.pformat(d2).splitlines())))
711 self.fail(self._formatMessage(msg, standardMsg))
712
713 def assertDictContainsSubset(self, expected, actual, msg=None):
714 """Checks whether actual is a superset of expected."""
715 missing = []
716 mismatched = []
717 for key, value in expected.iteritems():
718 if key not in actual:
719 missing.append(key)
720 elif value != actual[key]:
Georg Brandl46cc46a2009-10-01 20:11:14 +0000721 mismatched.append('%s, expected: %s, actual: %s' %
722 (key, value, actual[key]))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000723
724 if not (missing or mismatched):
725 return
726
727 standardMsg = ''
728 if missing:
729 standardMsg = 'Missing: %r' % ','.join(missing)
730 if mismatched:
731 if standardMsg:
732 standardMsg += '; '
733 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
734
735 self.fail(self._formatMessage(msg, standardMsg))
736
737 def assertSameElements(self, expected_seq, actual_seq, msg=None):
738 """An unordered sequence specific comparison.
739
740 Raises with an error message listing which elements of expected_seq
741 are missing from actual_seq and vice versa if any.
Michael Foordd0edec32010-02-05 22:55:09 +0000742
743 Duplicate elements are ignored when comparing *expected_seq* and
744 *actual_seq*. It is the equivalent of ``assertEqual(set(expected),
745 set(actual))`` but it works with sequences of unhashable objects as
746 well.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000747 """
748 try:
749 expected = set(expected_seq)
750 actual = set(actual_seq)
751 missing = list(expected.difference(actual))
752 unexpected = list(actual.difference(expected))
753 missing.sort()
754 unexpected.sort()
755 except TypeError:
756 # Fall back to slower list-compare if any of the objects are
757 # not hashable.
758 expected = list(expected_seq)
759 actual = list(actual_seq)
Antoine Pitroub9d49632010-01-04 23:22:44 +0000760 with warnings.catch_warnings():
761 if sys.py3kwarning:
762 # Silence Py3k warning
763 warnings.filterwarnings("ignore",
764 "dict inequality comparisons "
765 "not supported", DeprecationWarning)
766 expected.sort()
767 actual.sort()
768 missing, unexpected = util.sorted_list_difference(expected, actual)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000769 errors = []
770 if missing:
771 errors.append('Expected, but missing:\n %r' % missing)
772 if unexpected:
773 errors.append('Unexpected, but present:\n %r' % unexpected)
774 if errors:
775 standardMsg = '\n'.join(errors)
776 self.fail(self._formatMessage(msg, standardMsg))
777
778 def assertMultiLineEqual(self, first, second, msg=None):
779 """Assert that two multi-line strings are equal."""
780 self.assert_(isinstance(first, basestring), (
781 'First argument is not a string'))
782 self.assert_(isinstance(second, basestring), (
783 'Second argument is not a string'))
784
785 if first != second:
Georg Brandl46cc46a2009-10-01 20:11:14 +0000786 standardMsg = '\n' + ''.join(difflib.ndiff(first.splitlines(True),
787 second.splitlines(True)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000788 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
Georg Brandlf895cf52009-10-01 20:59:31 +0000826 def assertIsInstance(self, obj, cls, msg=None):
827 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
828 default message."""
829 if not isinstance(obj, cls):
830 standardMsg = '%r is not an instance of %r' % (obj, cls)
831 self.fail(self._formatMessage(msg, standardMsg))
832
833 def assertNotIsInstance(self, obj, cls, msg=None):
834 """Included for symmetry with assertIsInstance."""
835 if isinstance(obj, cls):
836 standardMsg = '%r is an instance of %r' % (obj, cls)
837 self.fail(self._formatMessage(msg, standardMsg))
838
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000839 def assertRaisesRegexp(self, expected_exception, expected_regexp,
840 callable_obj=None, *args, **kwargs):
841 """Asserts that the message in a raised exception matches a regexp.
842
843 Args:
844 expected_exception: Exception class expected to be raised.
845 expected_regexp: Regexp (re pattern object or string) expected
846 to be found in error message.
847 callable_obj: Function to be called.
848 args: Extra args.
849 kwargs: Extra kwargs.
850 """
851 context = _AssertRaisesContext(expected_exception, self, expected_regexp)
852 if callable_obj is None:
853 return context
854 with context:
855 callable_obj(*args, **kwargs)
856
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000857 def assertRegexpMatches(self, text, expected_regexp, msg=None):
858 if isinstance(expected_regexp, basestring):
859 expected_regexp = re.compile(expected_regexp)
860 if not expected_regexp.search(text):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000861 msg = msg or "Regexp didn't match"
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000862 msg = '%s: %r not found in %r' % (msg, expected_regexp.pattern, text)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000863 raise self.failureException(msg)
864
865
866class FunctionTestCase(TestCase):
867 """A test case that wraps a test function.
868
869 This is useful for slipping pre-existing test functions into the
870 unittest framework. Optionally, set-up and tidy-up functions can be
871 supplied. As with TestCase, the tidy-up ('tearDown') function will
872 always be called if the set-up ('setUp') function ran successfully.
873 """
874
875 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
876 super(FunctionTestCase, self).__init__()
877 self._setUpFunc = setUp
878 self._tearDownFunc = tearDown
879 self._testFunc = testFunc
880 self._description = description
881
882 def setUp(self):
883 if self._setUpFunc is not None:
884 self._setUpFunc()
885
886 def tearDown(self):
887 if self._tearDownFunc is not None:
888 self._tearDownFunc()
889
890 def runTest(self):
891 self._testFunc()
892
893 def id(self):
894 return self._testFunc.__name__
895
896 def __eq__(self, other):
897 if not isinstance(other, self.__class__):
898 return NotImplemented
899
900 return self._setUpFunc == other._setUpFunc and \
901 self._tearDownFunc == other._tearDownFunc and \
902 self._testFunc == other._testFunc and \
903 self._description == other._description
904
905 def __ne__(self, other):
906 return not self == other
907
908 def __hash__(self):
909 return hash((type(self), self._setUpFunc, self._tearDownFunc,
910 self._testFunc, self._description))
911
912 def __str__(self):
913 return "%s (%s)" % (util.strclass(self.__class__),
914 self._testFunc.__name__)
915
916 def __repr__(self):
917 return "<%s testFunc=%s>" % (util.strclass(self.__class__),
918 self._testFunc)
919
920 def shortDescription(self):
921 if self._description is not None:
922 return self._description
923 doc = self._testFunc.__doc__
924 return doc and doc.split("\n")[0].strip() or None