blob: 8de36d7512b53de0484c7bc199aa1770b159b0a5 [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
Michael Foord225a0992010-02-18 20:30:09 +000010from . import result
11from .util import strclass, safe_repr, sorted_list_difference
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +000012
13
14class SkipTest(Exception):
15 """
16 Raise this exception in a test to skip it.
17
18 Usually you can use TestResult.skip() or one of the skipping decorators
19 instead of raising this directly.
20 """
21 pass
22
23class _ExpectedFailure(Exception):
24 """
25 Raise this when a test is expected to fail.
26
27 This is an implementation detail.
28 """
29
30 def __init__(self, exc_info):
31 super(_ExpectedFailure, self).__init__()
32 self.exc_info = exc_info
33
34class _UnexpectedSuccess(Exception):
35 """
36 The test was supposed to fail, but it didn't!
37 """
38 pass
39
40def _id(obj):
41 return obj
42
43def skip(reason):
44 """
45 Unconditionally skip a test.
46 """
47 def decorator(test_item):
48 if isinstance(test_item, type) and issubclass(test_item, TestCase):
49 test_item.__unittest_skip__ = True
50 test_item.__unittest_skip_why__ = reason
51 return test_item
52 @functools.wraps(test_item)
53 def skip_wrapper(*args, **kwargs):
54 raise SkipTest(reason)
55 return skip_wrapper
56 return decorator
57
58def skipIf(condition, reason):
59 """
60 Skip a test if the condition is true.
61 """
62 if condition:
63 return skip(reason)
64 return _id
65
66def skipUnless(condition, reason):
67 """
68 Skip a test unless the condition is true.
69 """
70 if not condition:
71 return skip(reason)
72 return _id
73
74
75def expectedFailure(func):
76 @functools.wraps(func)
77 def wrapper(*args, **kwargs):
78 try:
79 func(*args, **kwargs)
80 except Exception:
81 raise _ExpectedFailure(sys.exc_info())
82 raise _UnexpectedSuccess
83 return wrapper
84
85
86class _AssertRaisesContext(object):
87 """A context manager used to implement TestCase.assertRaises* methods."""
88
89 def __init__(self, expected, test_case, expected_regexp=None):
90 self.expected = expected
91 self.failureException = test_case.failureException
Georg Brandlb0eb4d32010-02-07 11:34:15 +000092 self.expected_regexp = expected_regexp
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +000093
94 def __enter__(self):
Michael Foord2bd52dc2010-02-07 18:44:12 +000095 return self
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +000096
97 def __exit__(self, exc_type, exc_value, tb):
98 if exc_type is None:
99 try:
100 exc_name = self.expected.__name__
101 except AttributeError:
102 exc_name = str(self.expected)
103 raise self.failureException(
104 "{0} not raised".format(exc_name))
105 if not issubclass(exc_type, self.expected):
106 # let unexpected exceptions pass through
107 return False
Georg Brandldc3694b2010-02-07 17:02:22 +0000108 self.exception = exc_value # store for later retrieval
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000109 if self.expected_regexp is None:
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000110 return True
111
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000112 expected_regexp = self.expected_regexp
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000113 if isinstance(expected_regexp, basestring):
114 expected_regexp = re.compile(expected_regexp)
115 if not expected_regexp.search(str(exc_value)):
116 raise self.failureException('"%s" does not match "%s"' %
117 (expected_regexp.pattern, str(exc_value)))
118 return True
119
120
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000121class TestCase(object):
122 """A class whose instances are single test cases.
123
124 By default, the test code itself should be placed in a method named
125 'runTest'.
126
127 If the fixture may be used for many test cases, create as
128 many test methods as are needed. When instantiating such a TestCase
129 subclass, specify in the constructor arguments the name of the test method
130 that the instance is to execute.
131
132 Test authors should subclass TestCase for their own tests. Construction
133 and deconstruction of the test's environment ('fixture') can be
134 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
135
136 If it is necessary to override the __init__ method, the base class
137 __init__ method must always be called. It is important that subclasses
138 should not change the signature of their __init__ method, since instances
139 of the classes are instantiated automatically by parts of the framework
140 in order to be run.
141 """
142
143 # This attribute determines which exception will be raised when
144 # the instance's assertion methods fail; test methods raising this
145 # exception will be deemed to have 'failed' rather than 'errored'
146
147 failureException = AssertionError
148
149 # This attribute determines whether long messages (including repr of
150 # objects used in assert methods) will be printed on failure in *addition*
151 # to any explicit message passed.
152
153 longMessage = False
154
155
156 def __init__(self, methodName='runTest'):
157 """Create an instance of the class that will use the named test
158 method when executed. Raises a ValueError if the instance does
159 not have a method with the specified name.
160 """
161 self._testMethodName = methodName
162 self._resultForDoCleanups = None
163 try:
164 testMethod = getattr(self, methodName)
165 except AttributeError:
Michael Foordc2294dd2010-02-18 21:37:07 +0000166 raise ValueError("no such test method in %s: %s" %
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000167 (self.__class__, methodName))
168 self._testMethodDoc = testMethod.__doc__
169 self._cleanups = []
170
171 # Map types to custom assertEqual functions that will compare
172 # instances of said type in more detail to generate a more useful
173 # error message.
174 self._type_equality_funcs = {}
175 self.addTypeEqualityFunc(dict, self.assertDictEqual)
176 self.addTypeEqualityFunc(list, self.assertListEqual)
177 self.addTypeEqualityFunc(tuple, self.assertTupleEqual)
178 self.addTypeEqualityFunc(set, self.assertSetEqual)
179 self.addTypeEqualityFunc(frozenset, self.assertSetEqual)
Michael Foordfe6349c2010-02-08 22:41:16 +0000180 self.addTypeEqualityFunc(unicode, self.assertMultiLineEqual)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000181
182 def addTypeEqualityFunc(self, typeobj, function):
183 """Add a type specific assertEqual style function to compare a type.
184
185 This method is for use by TestCase subclasses that need to register
186 their own type equality functions to provide nicer error messages.
187
188 Args:
189 typeobj: The data type to call this function on when both values
190 are of the same type in assertEqual().
191 function: The callable taking two arguments and an optional
192 msg= argument that raises self.failureException with a
193 useful error message when the two arguments are not equal.
194 """
Benjamin Petersond46430b2009-11-29 22:26:26 +0000195 self._type_equality_funcs[typeobj] = function
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000196
197 def addCleanup(self, function, *args, **kwargs):
198 """Add a function, with arguments, to be called when the test is
199 completed. Functions added are called on a LIFO basis and are
200 called after tearDown on test failure or success.
201
202 Cleanup items are called even if setUp fails (unlike tearDown)."""
203 self._cleanups.append((function, args, kwargs))
204
205 def setUp(self):
206 "Hook method for setting up the test fixture before exercising it."
207 pass
208
209 def tearDown(self):
210 "Hook method for deconstructing the test fixture after testing it."
211 pass
212
213 def countTestCases(self):
214 return 1
215
216 def defaultTestResult(self):
217 return result.TestResult()
218
219 def shortDescription(self):
Michael Foorddb43b5a2010-02-10 14:25:12 +0000220 """Returns a one-line description of the test, or None if no
221 description has been provided.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000222
Michael Foorddb43b5a2010-02-10 14:25:12 +0000223 The default implementation of this method returns the first line of
224 the specified test method's docstring.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000225 """
Michael Foorddb43b5a2010-02-10 14:25:12 +0000226 doc = self._testMethodDoc
227 return doc and doc.split("\n")[0].strip() or None
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000228
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000229
230 def id(self):
Michael Foord225a0992010-02-18 20:30:09 +0000231 return "%s.%s" % (strclass(self.__class__), self._testMethodName)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000232
233 def __eq__(self, other):
234 if type(self) is not type(other):
235 return NotImplemented
236
237 return self._testMethodName == other._testMethodName
238
239 def __ne__(self, other):
240 return not self == other
241
242 def __hash__(self):
243 return hash((type(self), self._testMethodName))
244
245 def __str__(self):
Michael Foord225a0992010-02-18 20:30:09 +0000246 return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000247
248 def __repr__(self):
249 return "<%s testMethod=%s>" % \
Michael Foord225a0992010-02-18 20:30:09 +0000250 (strclass(self.__class__), self._testMethodName)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000251
252 def run(self, result=None):
253 orig_result = result
254 if result is None:
255 result = self.defaultTestResult()
256 startTestRun = getattr(result, 'startTestRun', None)
257 if startTestRun is not None:
258 startTestRun()
259
260 self._resultForDoCleanups = result
261 result.startTest(self)
262 if getattr(self.__class__, "__unittest_skip__", False):
263 # If the whole class was skipped.
264 try:
265 result.addSkip(self, self.__class__.__unittest_skip_why__)
266 finally:
267 result.stopTest(self)
268 return
269 testMethod = getattr(self, self._testMethodName)
270 try:
271 success = False
272 try:
273 self.setUp()
274 except SkipTest as e:
275 result.addSkip(self, str(e))
276 except Exception:
277 result.addError(self, sys.exc_info())
278 else:
279 try:
280 testMethod()
281 except self.failureException:
282 result.addFailure(self, sys.exc_info())
283 except _ExpectedFailure as e:
284 result.addExpectedFailure(self, e.exc_info)
285 except _UnexpectedSuccess:
286 result.addUnexpectedSuccess(self)
287 except SkipTest as e:
288 result.addSkip(self, str(e))
289 except Exception:
290 result.addError(self, sys.exc_info())
291 else:
292 success = True
293
294 try:
295 self.tearDown()
296 except Exception:
297 result.addError(self, sys.exc_info())
298 success = False
299
300 cleanUpSuccess = self.doCleanups()
301 success = success and cleanUpSuccess
302 if success:
303 result.addSuccess(self)
304 finally:
305 result.stopTest(self)
306 if orig_result is None:
307 stopTestRun = getattr(result, 'stopTestRun', None)
308 if stopTestRun is not None:
309 stopTestRun()
310
311 def doCleanups(self):
312 """Execute all cleanup functions. Normally called for you after
313 tearDown."""
314 result = self._resultForDoCleanups
315 ok = True
316 while self._cleanups:
317 function, args, kwargs = self._cleanups.pop(-1)
318 try:
319 function(*args, **kwargs)
320 except Exception:
321 ok = False
322 result.addError(self, sys.exc_info())
323 return ok
324
325 def __call__(self, *args, **kwds):
326 return self.run(*args, **kwds)
327
328 def debug(self):
329 """Run the test without collecting errors in a TestResult"""
330 self.setUp()
331 getattr(self, self._testMethodName)()
332 self.tearDown()
333
334 def skipTest(self, reason):
335 """Skip this test."""
336 raise SkipTest(reason)
337
338 def fail(self, msg=None):
339 """Fail immediately, with the given message."""
340 raise self.failureException(msg)
341
342 def assertFalse(self, expr, msg=None):
343 "Fail the test if the expression is true."
344 if expr:
Michael Foord225a0992010-02-18 20:30:09 +0000345 msg = self._formatMessage(msg, "%s is not False" % safe_repr(expr))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000346 raise self.failureException(msg)
347
348 def assertTrue(self, expr, msg=None):
349 """Fail the test unless the expression is true."""
350 if not expr:
Michael Foord225a0992010-02-18 20:30:09 +0000351 msg = self._formatMessage(msg, "%s is not True" % safe_repr(expr))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000352 raise self.failureException(msg)
353
354 def _formatMessage(self, msg, standardMsg):
355 """Honour the longMessage attribute when generating failure messages.
356 If longMessage is False this means:
357 * Use only an explicit message if it is provided
358 * Otherwise use the standard message for the assert
359
360 If longMessage is True:
361 * Use the standard message
362 * If an explicit message is provided, plus ' : ' and the explicit message
363 """
364 if not self.longMessage:
365 return msg or standardMsg
366 if msg is None:
367 return standardMsg
368 return standardMsg + ' : ' + msg
369
370
371 def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
372 """Fail unless an exception of class excClass is thrown
373 by callableObj when invoked with arguments args and keyword
374 arguments kwargs. If a different type of exception is
375 thrown, it will not be caught, and the test case will be
376 deemed to have suffered an error, exactly as for an
377 unexpected exception.
378
379 If called with callableObj omitted or None, will return a
380 context object used like this::
381
Michael Foordd0edec32010-02-05 22:55:09 +0000382 with self.assertRaises(SomeException):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000383 do_something()
Michael Foordd0edec32010-02-05 22:55:09 +0000384
385 The context manager keeps a reference to the exception as
Ezio Melotticd4f6572010-02-08 21:52:08 +0000386 the 'exception' attribute. This allows you to inspect the
Michael Foordd0edec32010-02-05 22:55:09 +0000387 exception after the assertion::
388
389 with self.assertRaises(SomeException) as cm:
390 do_something()
Georg Brandldc3694b2010-02-07 17:02:22 +0000391 the_exception = cm.exception
Michael Foord757cc4d2010-02-05 23:22:37 +0000392 self.assertEqual(the_exception.error_code, 3)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000393 """
394 context = _AssertRaisesContext(excClass, self)
395 if callableObj is None:
396 return context
397 with context:
398 callableObj(*args, **kwargs)
399
400 def _getAssertEqualityFunc(self, first, second):
401 """Get a detailed comparison function for the types of the two args.
402
403 Returns: A callable accepting (first, second, msg=None) that will
404 raise a failure exception if first != second with a useful human
405 readable error message for those types.
406 """
407 #
408 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
409 # and vice versa. I opted for the conservative approach in case
410 # subclasses are not intended to be compared in detail to their super
411 # class instances using a type equality func. This means testing
412 # subtypes won't automagically use the detailed comparison. Callers
413 # should use their type specific assertSpamEqual method to compare
414 # subclasses if the detailed comparison is desired and appropriate.
415 # See the discussion in http://bugs.python.org/issue2578.
416 #
417 if type(first) is type(second):
418 asserter = self._type_equality_funcs.get(type(first))
419 if asserter is not None:
Benjamin Petersond46430b2009-11-29 22:26:26 +0000420 return asserter
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000421
422 return self._baseAssertEqual
423
424 def _baseAssertEqual(self, first, second, msg=None):
425 """The default assertEqual implementation, not type specific."""
426 if not first == second:
Michael Foord225a0992010-02-18 20:30:09 +0000427 standardMsg = '%s != %s' % (safe_repr(first), safe_repr(second))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000428 msg = self._formatMessage(msg, standardMsg)
429 raise self.failureException(msg)
430
431 def assertEqual(self, first, second, msg=None):
432 """Fail if the two objects are unequal as determined by the '=='
433 operator.
434 """
435 assertion_func = self._getAssertEqualityFunc(first, second)
436 assertion_func(first, second, msg=msg)
437
438 def assertNotEqual(self, first, second, msg=None):
439 """Fail if the two objects are equal as determined by the '=='
440 operator.
441 """
442 if not first != second:
Michael Foord225a0992010-02-18 20:30:09 +0000443 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
444 safe_repr(second)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000445 raise self.failureException(msg)
446
447 def assertAlmostEqual(self, first, second, places=7, msg=None):
448 """Fail if the two objects are unequal as determined by their
449 difference rounded to the given number of decimal places
450 (default 7) and comparing to zero.
451
452 Note that decimal places (from zero) are usually not the same
453 as significant digits (measured from the most signficant digit).
Michael Foordc3f79372009-09-13 16:40:02 +0000454
455 If the two objects compare equal then they will automatically
456 compare almost equal.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000457 """
Michael Foordc3f79372009-09-13 16:40:02 +0000458 if first == second:
Michael Foord225a0992010-02-18 20:30:09 +0000459 # shortcut for inf
Michael Foordc3f79372009-09-13 16:40:02 +0000460 return
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000461 if round(abs(second-first), places) != 0:
Michael Foord225a0992010-02-18 20:30:09 +0000462 standardMsg = '%s != %s within %r places' % (safe_repr(first),
463 safe_repr(second),
464 places)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000465 msg = self._formatMessage(msg, standardMsg)
466 raise self.failureException(msg)
467
468 def assertNotAlmostEqual(self, first, second, places=7, msg=None):
469 """Fail if the two objects are equal as determined by their
470 difference rounded to the given number of decimal places
471 (default 7) and comparing to zero.
472
473 Note that decimal places (from zero) are usually not the same
474 as significant digits (measured from the most signficant digit).
Michael Foordc3f79372009-09-13 16:40:02 +0000475
476 Objects that are equal automatically fail.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000477 """
Michael Foordc3f79372009-09-13 16:40:02 +0000478 if (first == second) or round(abs(second-first), places) == 0:
Michael Foord225a0992010-02-18 20:30:09 +0000479 standardMsg = '%s == %s within %r places' % (safe_repr(first),
480 safe_repr(second),
481 places)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000482 msg = self._formatMessage(msg, standardMsg)
483 raise self.failureException(msg)
484
485 # Synonyms for assertion methods
486
487 # The plurals are undocumented. Keep them that way to discourage use.
488 # Do not add more. Do not remove.
489 # Going through a deprecation cycle on these would annoy many people.
490 assertEquals = assertEqual
491 assertNotEquals = assertNotEqual
492 assertAlmostEquals = assertAlmostEqual
493 assertNotAlmostEquals = assertNotAlmostEqual
Michael Foord67dfc772010-02-10 14:31:30 +0000494 assert_ = assertTrue
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000495
496 # These fail* assertion method names are pending deprecation and will
497 # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
498 def _deprecate(original_func):
499 def deprecated_func(*args, **kwargs):
500 warnings.warn(
501 'Please use {0} instead.'.format(original_func.__name__),
502 PendingDeprecationWarning, 2)
503 return original_func(*args, **kwargs)
504 return deprecated_func
505
506 failUnlessEqual = _deprecate(assertEqual)
507 failIfEqual = _deprecate(assertNotEqual)
508 failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
509 failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
510 failUnless = _deprecate(assertTrue)
511 failUnlessRaises = _deprecate(assertRaises)
512 failIf = _deprecate(assertFalse)
513
514 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
515 """An equality assertion for ordered sequences (like lists and tuples).
516
R. David Murray05b41712010-01-29 19:35:39 +0000517 For the purposes of this function, a valid ordered sequence type is one
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000518 which can be indexed, has a length, and has an equality operator.
519
520 Args:
521 seq1: The first sequence to compare.
522 seq2: The second sequence to compare.
523 seq_type: The expected datatype of the sequences, or None if no
524 datatype should be enforced.
525 msg: Optional message to use on failure instead of a list of
526 differences.
527 """
528 if seq_type != None:
529 seq_type_name = seq_type.__name__
530 if not isinstance(seq1, seq_type):
Michael Foord225a0992010-02-18 20:30:09 +0000531 raise self.failureException('First sequence is not a %s: %s'
532 % (seq_type_name, safe_repr(seq1)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000533 if not isinstance(seq2, seq_type):
Michael Foord225a0992010-02-18 20:30:09 +0000534 raise self.failureException('Second sequence is not a %s: %s'
535 % (seq_type_name, safe_repr(seq2)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000536 else:
537 seq_type_name = "sequence"
538
539 differing = None
540 try:
541 len1 = len(seq1)
542 except (TypeError, NotImplementedError):
543 differing = 'First %s has no length. Non-sequence?' % (
544 seq_type_name)
545
546 if differing is None:
547 try:
548 len2 = len(seq2)
549 except (TypeError, NotImplementedError):
550 differing = 'Second %s has no length. Non-sequence?' % (
551 seq_type_name)
552
553 if differing is None:
554 if seq1 == seq2:
555 return
556
Michael Foord225a0992010-02-18 20:30:09 +0000557 seq1_repr = safe_repr(seq1)
558 seq2_repr = safe_repr(seq2)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000559 if len(seq1_repr) > 30:
560 seq1_repr = seq1_repr[:30] + '...'
561 if len(seq2_repr) > 30:
562 seq2_repr = seq2_repr[:30] + '...'
563 elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
564 differing = '%ss differ: %s != %s\n' % elements
565
566 for i in xrange(min(len1, len2)):
567 try:
568 item1 = seq1[i]
569 except (TypeError, IndexError, NotImplementedError):
570 differing += ('\nUnable to index element %d of first %s\n' %
571 (i, seq_type_name))
572 break
573
574 try:
575 item2 = seq2[i]
576 except (TypeError, IndexError, NotImplementedError):
577 differing += ('\nUnable to index element %d of second %s\n' %
578 (i, seq_type_name))
579 break
580
581 if item1 != item2:
582 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
583 (i, item1, item2))
584 break
585 else:
586 if (len1 == len2 and seq_type is None and
587 type(seq1) != type(seq2)):
588 # The sequences are the same, but have differing types.
589 return
590
591 if len1 > len2:
592 differing += ('\nFirst %s contains %d additional '
593 'elements.\n' % (seq_type_name, len1 - len2))
594 try:
595 differing += ('First extra element %d:\n%s\n' %
596 (len2, seq1[len2]))
597 except (TypeError, IndexError, NotImplementedError):
598 differing += ('Unable to index element %d '
599 'of first %s\n' % (len2, seq_type_name))
600 elif len1 < len2:
601 differing += ('\nSecond %s contains %d additional '
602 'elements.\n' % (seq_type_name, len2 - len1))
603 try:
604 differing += ('First extra element %d:\n%s\n' %
605 (len1, seq2[len1]))
606 except (TypeError, IndexError, NotImplementedError):
607 differing += ('Unable to index element %d '
608 'of second %s\n' % (len1, seq_type_name))
Georg Brandl46cc46a2009-10-01 20:11:14 +0000609 standardMsg = differing + '\n' + '\n'.join(
610 difflib.ndiff(pprint.pformat(seq1).splitlines(),
611 pprint.pformat(seq2).splitlines()))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000612 msg = self._formatMessage(msg, standardMsg)
613 self.fail(msg)
614
615 def assertListEqual(self, list1, list2, msg=None):
616 """A list-specific equality assertion.
617
618 Args:
619 list1: The first list to compare.
620 list2: The second list to compare.
621 msg: Optional message to use on failure instead of a list of
622 differences.
623
624 """
625 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
626
627 def assertTupleEqual(self, tuple1, tuple2, msg=None):
628 """A tuple-specific equality assertion.
629
630 Args:
631 tuple1: The first tuple to compare.
632 tuple2: The second tuple to compare.
633 msg: Optional message to use on failure instead of a list of
634 differences.
635 """
636 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
637
638 def assertSetEqual(self, set1, set2, msg=None):
639 """A set-specific equality assertion.
640
641 Args:
642 set1: The first set to compare.
643 set2: The second set to compare.
644 msg: Optional message to use on failure instead of a list of
645 differences.
646
647 For more general containership equality, assertSameElements will work
648 with things other than sets. This uses ducktyping to support
649 different types of sets, and is optimized for sets specifically
650 (parameters must support a difference method).
651 """
652 try:
653 difference1 = set1.difference(set2)
654 except TypeError, e:
655 self.fail('invalid type when attempting set difference: %s' % e)
656 except AttributeError, e:
657 self.fail('first argument does not support set difference: %s' % e)
658
659 try:
660 difference2 = set2.difference(set1)
661 except TypeError, e:
662 self.fail('invalid type when attempting set difference: %s' % e)
663 except AttributeError, e:
664 self.fail('second argument does not support set difference: %s' % e)
665
666 if not (difference1 or difference2):
667 return
668
669 lines = []
670 if difference1:
671 lines.append('Items in the first set but not the second:')
672 for item in difference1:
673 lines.append(repr(item))
674 if difference2:
675 lines.append('Items in the second set but not the first:')
676 for item in difference2:
677 lines.append(repr(item))
678
679 standardMsg = '\n'.join(lines)
680 self.fail(self._formatMessage(msg, standardMsg))
681
682 def assertIn(self, member, container, msg=None):
683 """Just like self.assertTrue(a in b), but with a nicer default message."""
684 if member not in container:
Michael Foord225a0992010-02-18 20:30:09 +0000685 standardMsg = '%s not found in %s' % (safe_repr(member),
686 safe_repr(container))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000687 self.fail(self._formatMessage(msg, standardMsg))
688
689 def assertNotIn(self, member, container, msg=None):
690 """Just like self.assertTrue(a not in b), but with a nicer default message."""
691 if member in container:
Michael Foord225a0992010-02-18 20:30:09 +0000692 standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
693 safe_repr(container))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000694 self.fail(self._formatMessage(msg, standardMsg))
695
696 def assertIs(self, expr1, expr2, msg=None):
697 """Just like self.assertTrue(a is b), but with a nicer default message."""
698 if expr1 is not expr2:
Michael Foord225a0992010-02-18 20:30:09 +0000699 standardMsg = '%s is not %s' % (safe_repr(expr1),
Michael Foordc2294dd2010-02-18 21:37:07 +0000700 safe_repr(expr2))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000701 self.fail(self._formatMessage(msg, standardMsg))
702
703 def assertIsNot(self, expr1, expr2, msg=None):
704 """Just like self.assertTrue(a is not b), but with a nicer default message."""
705 if expr1 is expr2:
Michael Foord225a0992010-02-18 20:30:09 +0000706 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000707 self.fail(self._formatMessage(msg, standardMsg))
708
709 def assertDictEqual(self, d1, d2, msg=None):
710 self.assert_(isinstance(d1, dict), 'First argument is not a dictionary')
711 self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary')
712
713 if d1 != d2:
714 standardMsg = ('\n' + '\n'.join(difflib.ndiff(
715 pprint.pformat(d1).splitlines(),
716 pprint.pformat(d2).splitlines())))
717 self.fail(self._formatMessage(msg, standardMsg))
718
719 def assertDictContainsSubset(self, expected, actual, msg=None):
720 """Checks whether actual is a superset of expected."""
721 missing = []
722 mismatched = []
723 for key, value in expected.iteritems():
724 if key not in actual:
725 missing.append(key)
726 elif value != actual[key]:
Georg Brandl46cc46a2009-10-01 20:11:14 +0000727 mismatched.append('%s, expected: %s, actual: %s' %
Michael Foordc2294dd2010-02-18 21:37:07 +0000728 (safe_repr(key), safe_repr(value),
729 safe_repr(actual[key])))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000730
731 if not (missing or mismatched):
732 return
733
734 standardMsg = ''
735 if missing:
Michael Foord225a0992010-02-18 20:30:09 +0000736 standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
737 missing)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000738 if mismatched:
739 if standardMsg:
740 standardMsg += '; '
741 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
742
743 self.fail(self._formatMessage(msg, standardMsg))
744
745 def assertSameElements(self, expected_seq, actual_seq, msg=None):
746 """An unordered sequence specific comparison.
747
748 Raises with an error message listing which elements of expected_seq
749 are missing from actual_seq and vice versa if any.
Michael Foordd0edec32010-02-05 22:55:09 +0000750
751 Duplicate elements are ignored when comparing *expected_seq* and
752 *actual_seq*. It is the equivalent of ``assertEqual(set(expected),
753 set(actual))`` but it works with sequences of unhashable objects as
754 well.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000755 """
756 try:
757 expected = set(expected_seq)
758 actual = set(actual_seq)
759 missing = list(expected.difference(actual))
760 unexpected = list(actual.difference(expected))
761 missing.sort()
762 unexpected.sort()
763 except TypeError:
764 # Fall back to slower list-compare if any of the objects are
765 # not hashable.
766 expected = list(expected_seq)
767 actual = list(actual_seq)
Antoine Pitroub9d49632010-01-04 23:22:44 +0000768 with warnings.catch_warnings():
769 if sys.py3kwarning:
770 # Silence Py3k warning
771 warnings.filterwarnings("ignore",
772 "dict inequality comparisons "
773 "not supported", DeprecationWarning)
774 expected.sort()
775 actual.sort()
Michael Foord225a0992010-02-18 20:30:09 +0000776 missing, unexpected = sorted_list_difference(expected, actual)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000777 errors = []
778 if missing:
Michael Foord225a0992010-02-18 20:30:09 +0000779 errors.append('Expected, but missing:\n %s' %
780 safe_repr(missing))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000781 if unexpected:
Michael Foord225a0992010-02-18 20:30:09 +0000782 errors.append('Unexpected, but present:\n %s' %
783 safe_repr(unexpected))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000784 if errors:
785 standardMsg = '\n'.join(errors)
786 self.fail(self._formatMessage(msg, standardMsg))
787
788 def assertMultiLineEqual(self, first, second, msg=None):
789 """Assert that two multi-line strings are equal."""
790 self.assert_(isinstance(first, basestring), (
791 'First argument is not a string'))
792 self.assert_(isinstance(second, basestring), (
793 'Second argument is not a string'))
794
795 if first != second:
Georg Brandl46cc46a2009-10-01 20:11:14 +0000796 standardMsg = '\n' + ''.join(difflib.ndiff(first.splitlines(True),
797 second.splitlines(True)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000798 self.fail(self._formatMessage(msg, standardMsg))
799
800 def assertLess(self, a, b, msg=None):
801 """Just like self.assertTrue(a < b), but with a nicer default message."""
802 if not a < b:
Michael Foord225a0992010-02-18 20:30:09 +0000803 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000804 self.fail(self._formatMessage(msg, standardMsg))
805
806 def assertLessEqual(self, a, b, msg=None):
807 """Just like self.assertTrue(a <= b), but with a nicer default message."""
808 if not a <= b:
Michael Foord225a0992010-02-18 20:30:09 +0000809 standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000810 self.fail(self._formatMessage(msg, standardMsg))
811
812 def assertGreater(self, a, b, msg=None):
813 """Just like self.assertTrue(a > b), but with a nicer default message."""
814 if not a > b:
Michael Foord225a0992010-02-18 20:30:09 +0000815 standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000816 self.fail(self._formatMessage(msg, standardMsg))
817
818 def assertGreaterEqual(self, a, b, msg=None):
819 """Just like self.assertTrue(a >= b), but with a nicer default message."""
820 if not a >= b:
Michael Foord225a0992010-02-18 20:30:09 +0000821 standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000822 self.fail(self._formatMessage(msg, standardMsg))
823
824 def assertIsNone(self, obj, msg=None):
825 """Same as self.assertTrue(obj is None), with a nicer default message."""
826 if obj is not None:
Michael Foord225a0992010-02-18 20:30:09 +0000827 standardMsg = '%s is not None' % (safe_repr(obj),)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000828 self.fail(self._formatMessage(msg, standardMsg))
829
830 def assertIsNotNone(self, obj, msg=None):
831 """Included for symmetry with assertIsNone."""
832 if obj is None:
833 standardMsg = 'unexpectedly None'
834 self.fail(self._formatMessage(msg, standardMsg))
835
Georg Brandlf895cf52009-10-01 20:59:31 +0000836 def assertIsInstance(self, obj, cls, msg=None):
837 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
838 default message."""
839 if not isinstance(obj, cls):
Michael Foord225a0992010-02-18 20:30:09 +0000840 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
Georg Brandlf895cf52009-10-01 20:59:31 +0000841 self.fail(self._formatMessage(msg, standardMsg))
842
843 def assertNotIsInstance(self, obj, cls, msg=None):
844 """Included for symmetry with assertIsInstance."""
845 if isinstance(obj, cls):
Michael Foord225a0992010-02-18 20:30:09 +0000846 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
Georg Brandlf895cf52009-10-01 20:59:31 +0000847 self.fail(self._formatMessage(msg, standardMsg))
848
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000849 def assertRaisesRegexp(self, expected_exception, expected_regexp,
850 callable_obj=None, *args, **kwargs):
851 """Asserts that the message in a raised exception matches a regexp.
852
853 Args:
854 expected_exception: Exception class expected to be raised.
855 expected_regexp: Regexp (re pattern object or string) expected
856 to be found in error message.
857 callable_obj: Function to be called.
858 args: Extra args.
859 kwargs: Extra kwargs.
860 """
861 context = _AssertRaisesContext(expected_exception, self, expected_regexp)
862 if callable_obj is None:
863 return context
864 with context:
865 callable_obj(*args, **kwargs)
866
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000867 def assertRegexpMatches(self, text, expected_regexp, msg=None):
868 if isinstance(expected_regexp, basestring):
869 expected_regexp = re.compile(expected_regexp)
870 if not expected_regexp.search(text):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000871 msg = msg or "Regexp didn't match"
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000872 msg = '%s: %r not found in %r' % (msg, expected_regexp.pattern, text)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000873 raise self.failureException(msg)
874
875
876class FunctionTestCase(TestCase):
877 """A test case that wraps a test function.
878
879 This is useful for slipping pre-existing test functions into the
880 unittest framework. Optionally, set-up and tidy-up functions can be
881 supplied. As with TestCase, the tidy-up ('tearDown') function will
882 always be called if the set-up ('setUp') function ran successfully.
883 """
884
885 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
886 super(FunctionTestCase, self).__init__()
887 self._setUpFunc = setUp
888 self._tearDownFunc = tearDown
889 self._testFunc = testFunc
890 self._description = description
891
892 def setUp(self):
893 if self._setUpFunc is not None:
894 self._setUpFunc()
895
896 def tearDown(self):
897 if self._tearDownFunc is not None:
898 self._tearDownFunc()
899
900 def runTest(self):
901 self._testFunc()
902
903 def id(self):
904 return self._testFunc.__name__
905
906 def __eq__(self, other):
907 if not isinstance(other, self.__class__):
908 return NotImplemented
909
910 return self._setUpFunc == other._setUpFunc and \
911 self._tearDownFunc == other._tearDownFunc and \
912 self._testFunc == other._testFunc and \
913 self._description == other._description
914
915 def __ne__(self, other):
916 return not self == other
917
918 def __hash__(self):
919 return hash((type(self), self._setUpFunc, self._tearDownFunc,
920 self._testFunc, self._description))
921
922 def __str__(self):
Michael Foord225a0992010-02-18 20:30:09 +0000923 return "%s (%s)" % (strclass(self.__class__),
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000924 self._testFunc.__name__)
925
926 def __repr__(self):
Michael Foord225a0992010-02-18 20:30:09 +0000927 return "<%s tec=%s>" % (strclass(self.__class__),
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000928 self._testFunc)
929
930 def shortDescription(self):
931 if self._description is not None:
932 return self._description
933 doc = self._testFunc.__doc__
934 return doc and doc.split("\n")[0].strip() or None