blob: 0bfcc757acff3acf9e007c003ae14a783c53a1f4 [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):
Michael Foord53e8eea2010-03-07 20:22:12 +000048 if not (isinstance(test_item, type) and issubclass(test_item, TestCase)):
49 @functools.wraps(test_item)
50 def skip_wrapper(*args, **kwargs):
51 raise SkipTest(reason)
52 test_item = skip_wrapper
53
54 test_item.__unittest_skip__ = True
55 test_item.__unittest_skip_why__ = reason
56 return test_item
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +000057 return decorator
58
59def skipIf(condition, reason):
60 """
61 Skip a test if the condition is true.
62 """
63 if condition:
64 return skip(reason)
65 return _id
66
67def skipUnless(condition, reason):
68 """
69 Skip a test unless the condition is true.
70 """
71 if not condition:
72 return skip(reason)
73 return _id
74
75
76def expectedFailure(func):
77 @functools.wraps(func)
78 def wrapper(*args, **kwargs):
79 try:
80 func(*args, **kwargs)
81 except Exception:
82 raise _ExpectedFailure(sys.exc_info())
83 raise _UnexpectedSuccess
84 return wrapper
85
86
87class _AssertRaisesContext(object):
88 """A context manager used to implement TestCase.assertRaises* methods."""
89
90 def __init__(self, expected, test_case, expected_regexp=None):
91 self.expected = expected
92 self.failureException = test_case.failureException
Georg Brandlb0eb4d32010-02-07 11:34:15 +000093 self.expected_regexp = expected_regexp
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +000094
95 def __enter__(self):
Michael Foord2bd52dc2010-02-07 18:44:12 +000096 return self
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +000097
98 def __exit__(self, exc_type, exc_value, tb):
99 if exc_type is None:
100 try:
101 exc_name = self.expected.__name__
102 except AttributeError:
103 exc_name = str(self.expected)
104 raise self.failureException(
105 "{0} not raised".format(exc_name))
106 if not issubclass(exc_type, self.expected):
107 # let unexpected exceptions pass through
108 return False
Georg Brandldc3694b2010-02-07 17:02:22 +0000109 self.exception = exc_value # store for later retrieval
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000110 if self.expected_regexp is None:
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000111 return True
112
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000113 expected_regexp = self.expected_regexp
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000114 if isinstance(expected_regexp, basestring):
115 expected_regexp = re.compile(expected_regexp)
116 if not expected_regexp.search(str(exc_value)):
117 raise self.failureException('"%s" does not match "%s"' %
118 (expected_regexp.pattern, str(exc_value)))
119 return True
120
121
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000122class TestCase(object):
123 """A class whose instances are single test cases.
124
125 By default, the test code itself should be placed in a method named
126 'runTest'.
127
128 If the fixture may be used for many test cases, create as
129 many test methods as are needed. When instantiating such a TestCase
130 subclass, specify in the constructor arguments the name of the test method
131 that the instance is to execute.
132
133 Test authors should subclass TestCase for their own tests. Construction
134 and deconstruction of the test's environment ('fixture') can be
135 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
136
137 If it is necessary to override the __init__ method, the base class
138 __init__ method must always be called. It is important that subclasses
139 should not change the signature of their __init__ method, since instances
140 of the classes are instantiated automatically by parts of the framework
141 in order to be run.
142 """
143
144 # This attribute determines which exception will be raised when
145 # the instance's assertion methods fail; test methods raising this
146 # exception will be deemed to have 'failed' rather than 'errored'
147
148 failureException = AssertionError
149
150 # This attribute determines whether long messages (including repr of
151 # objects used in assert methods) will be printed on failure in *addition*
152 # to any explicit message passed.
153
154 longMessage = False
155
Michael Foord5ffa3252010-03-07 22:04:55 +0000156 # Attribute used by TestSuite for classSetUp
157
158 _classSetupFailed = False
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000159
160 def __init__(self, methodName='runTest'):
161 """Create an instance of the class that will use the named test
162 method when executed. Raises a ValueError if the instance does
163 not have a method with the specified name.
164 """
165 self._testMethodName = methodName
166 self._resultForDoCleanups = None
167 try:
168 testMethod = getattr(self, methodName)
169 except AttributeError:
Michael Foordc2294dd2010-02-18 21:37:07 +0000170 raise ValueError("no such test method in %s: %s" %
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000171 (self.__class__, methodName))
172 self._testMethodDoc = testMethod.__doc__
173 self._cleanups = []
174
175 # Map types to custom assertEqual functions that will compare
176 # instances of said type in more detail to generate a more useful
177 # error message.
178 self._type_equality_funcs = {}
179 self.addTypeEqualityFunc(dict, self.assertDictEqual)
180 self.addTypeEqualityFunc(list, self.assertListEqual)
181 self.addTypeEqualityFunc(tuple, self.assertTupleEqual)
182 self.addTypeEqualityFunc(set, self.assertSetEqual)
183 self.addTypeEqualityFunc(frozenset, self.assertSetEqual)
Michael Foordfe6349c2010-02-08 22:41:16 +0000184 self.addTypeEqualityFunc(unicode, self.assertMultiLineEqual)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000185
186 def addTypeEqualityFunc(self, typeobj, function):
187 """Add a type specific assertEqual style function to compare a type.
188
189 This method is for use by TestCase subclasses that need to register
190 their own type equality functions to provide nicer error messages.
191
192 Args:
193 typeobj: The data type to call this function on when both values
194 are of the same type in assertEqual().
195 function: The callable taking two arguments and an optional
196 msg= argument that raises self.failureException with a
197 useful error message when the two arguments are not equal.
198 """
Benjamin Petersond46430b2009-11-29 22:26:26 +0000199 self._type_equality_funcs[typeobj] = function
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000200
201 def addCleanup(self, function, *args, **kwargs):
202 """Add a function, with arguments, to be called when the test is
203 completed. Functions added are called on a LIFO basis and are
204 called after tearDown on test failure or success.
205
206 Cleanup items are called even if setUp fails (unlike tearDown)."""
207 self._cleanups.append((function, args, kwargs))
208
209 def setUp(self):
210 "Hook method for setting up the test fixture before exercising it."
211 pass
212
213 def tearDown(self):
214 "Hook method for deconstructing the test fixture after testing it."
215 pass
216
Michael Foord5ffa3252010-03-07 22:04:55 +0000217 @classmethod
218 def setUpClass(cls):
219 "Hook method for setting up class fixture before running tests in the class."
220
221 @classmethod
222 def tearDownClass(cls):
223 "Hook method for deconstructing the class fixture after running all tests in the class."
224
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000225 def countTestCases(self):
226 return 1
227
228 def defaultTestResult(self):
229 return result.TestResult()
230
231 def shortDescription(self):
Michael Foorddb43b5a2010-02-10 14:25:12 +0000232 """Returns a one-line description of the test, or None if no
233 description has been provided.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000234
Michael Foorddb43b5a2010-02-10 14:25:12 +0000235 The default implementation of this method returns the first line of
236 the specified test method's docstring.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000237 """
Michael Foorddb43b5a2010-02-10 14:25:12 +0000238 doc = self._testMethodDoc
239 return doc and doc.split("\n")[0].strip() or None
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000240
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000241
242 def id(self):
Michael Foord225a0992010-02-18 20:30:09 +0000243 return "%s.%s" % (strclass(self.__class__), self._testMethodName)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000244
245 def __eq__(self, other):
246 if type(self) is not type(other):
247 return NotImplemented
248
249 return self._testMethodName == other._testMethodName
250
251 def __ne__(self, other):
252 return not self == other
253
254 def __hash__(self):
255 return hash((type(self), self._testMethodName))
256
257 def __str__(self):
Michael Foord225a0992010-02-18 20:30:09 +0000258 return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000259
260 def __repr__(self):
261 return "<%s testMethod=%s>" % \
Michael Foord225a0992010-02-18 20:30:09 +0000262 (strclass(self.__class__), self._testMethodName)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000263
Michael Foordae3db0a2010-02-22 23:28:32 +0000264 def _addSkip(self, result, reason):
265 addSkip = getattr(result, 'addSkip', None)
266 if addSkip is not None:
267 addSkip(self, reason)
268 else:
269 warnings.warn("TestResult has no addSkip method, skips not reported",
270 RuntimeWarning, 2)
271 result.addSuccess(self)
272
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000273 def run(self, result=None):
274 orig_result = result
275 if result is None:
276 result = self.defaultTestResult()
277 startTestRun = getattr(result, 'startTestRun', None)
278 if startTestRun is not None:
279 startTestRun()
280
281 self._resultForDoCleanups = result
282 result.startTest(self)
Michael Foord53e8eea2010-03-07 20:22:12 +0000283
284 testMethod = getattr(self, self._testMethodName)
285 if (getattr(self.__class__, "__unittest_skip__", False) or
286 getattr(testMethod, "__unittest_skip__", False)):
287 # If the class or method was skipped.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000288 try:
Michael Foord53e8eea2010-03-07 20:22:12 +0000289 skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
290 or getattr(testMethod, '__unittest_skip_why__', ''))
291 self._addSkip(result, skip_why)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000292 finally:
293 result.stopTest(self)
294 return
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000295 try:
296 success = False
297 try:
298 self.setUp()
299 except SkipTest as e:
Michael Foordae3db0a2010-02-22 23:28:32 +0000300 self._addSkip(result, str(e))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000301 except Exception:
302 result.addError(self, sys.exc_info())
303 else:
304 try:
305 testMethod()
306 except self.failureException:
307 result.addFailure(self, sys.exc_info())
308 except _ExpectedFailure as e:
Michael Foordae3db0a2010-02-22 23:28:32 +0000309 addExpectedFailure = getattr(result, 'addExpectedFailure', None)
310 if addExpectedFailure is not None:
311 addExpectedFailure(self, e.exc_info)
312 else:
313 warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
314 RuntimeWarning)
315 result.addSuccess(self)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000316 except _UnexpectedSuccess:
Michael Foordae3db0a2010-02-22 23:28:32 +0000317 addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
318 if addUnexpectedSuccess is not None:
319 addUnexpectedSuccess(self)
320 else:
321 warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures",
322 RuntimeWarning)
323 result.addFailure(self, sys.exc_info())
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000324 except SkipTest as e:
Michael Foordae3db0a2010-02-22 23:28:32 +0000325 self._addSkip(result, str(e))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000326 except Exception:
327 result.addError(self, sys.exc_info())
328 else:
329 success = True
330
331 try:
332 self.tearDown()
333 except Exception:
334 result.addError(self, sys.exc_info())
335 success = False
336
337 cleanUpSuccess = self.doCleanups()
338 success = success and cleanUpSuccess
339 if success:
340 result.addSuccess(self)
341 finally:
342 result.stopTest(self)
343 if orig_result is None:
344 stopTestRun = getattr(result, 'stopTestRun', None)
345 if stopTestRun is not None:
346 stopTestRun()
347
348 def doCleanups(self):
349 """Execute all cleanup functions. Normally called for you after
350 tearDown."""
351 result = self._resultForDoCleanups
352 ok = True
353 while self._cleanups:
354 function, args, kwargs = self._cleanups.pop(-1)
355 try:
356 function(*args, **kwargs)
357 except Exception:
358 ok = False
359 result.addError(self, sys.exc_info())
360 return ok
361
362 def __call__(self, *args, **kwds):
363 return self.run(*args, **kwds)
364
365 def debug(self):
366 """Run the test without collecting errors in a TestResult"""
367 self.setUp()
368 getattr(self, self._testMethodName)()
369 self.tearDown()
370
371 def skipTest(self, reason):
372 """Skip this test."""
373 raise SkipTest(reason)
374
375 def fail(self, msg=None):
376 """Fail immediately, with the given message."""
377 raise self.failureException(msg)
378
379 def assertFalse(self, expr, msg=None):
380 "Fail the test if the expression is true."
381 if expr:
Michael Foord225a0992010-02-18 20:30:09 +0000382 msg = self._formatMessage(msg, "%s is not False" % safe_repr(expr))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000383 raise self.failureException(msg)
384
385 def assertTrue(self, expr, msg=None):
386 """Fail the test unless the expression is true."""
387 if not expr:
Michael Foord225a0992010-02-18 20:30:09 +0000388 msg = self._formatMessage(msg, "%s is not True" % safe_repr(expr))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000389 raise self.failureException(msg)
390
391 def _formatMessage(self, msg, standardMsg):
392 """Honour the longMessage attribute when generating failure messages.
393 If longMessage is False this means:
394 * Use only an explicit message if it is provided
395 * Otherwise use the standard message for the assert
396
397 If longMessage is True:
398 * Use the standard message
399 * If an explicit message is provided, plus ' : ' and the explicit message
400 """
401 if not self.longMessage:
402 return msg or standardMsg
403 if msg is None:
404 return standardMsg
Michael Foord53e8eea2010-03-07 20:22:12 +0000405 try:
406 # don't switch to '{}' formatting in Python 2.X
407 # it changes the way unicode input is handled
408 return '%s : %s' % (standardMsg, msg)
409 except UnicodeDecodeError:
410 return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000411
412
413 def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
414 """Fail unless an exception of class excClass is thrown
415 by callableObj when invoked with arguments args and keyword
416 arguments kwargs. If a different type of exception is
417 thrown, it will not be caught, and the test case will be
418 deemed to have suffered an error, exactly as for an
419 unexpected exception.
420
421 If called with callableObj omitted or None, will return a
422 context object used like this::
423
Michael Foordd0edec32010-02-05 22:55:09 +0000424 with self.assertRaises(SomeException):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000425 do_something()
Michael Foordd0edec32010-02-05 22:55:09 +0000426
427 The context manager keeps a reference to the exception as
Ezio Melotticd4f6572010-02-08 21:52:08 +0000428 the 'exception' attribute. This allows you to inspect the
Michael Foordd0edec32010-02-05 22:55:09 +0000429 exception after the assertion::
430
431 with self.assertRaises(SomeException) as cm:
432 do_something()
Georg Brandldc3694b2010-02-07 17:02:22 +0000433 the_exception = cm.exception
Michael Foord757cc4d2010-02-05 23:22:37 +0000434 self.assertEqual(the_exception.error_code, 3)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000435 """
436 context = _AssertRaisesContext(excClass, self)
437 if callableObj is None:
438 return context
439 with context:
440 callableObj(*args, **kwargs)
441
442 def _getAssertEqualityFunc(self, first, second):
443 """Get a detailed comparison function for the types of the two args.
444
445 Returns: A callable accepting (first, second, msg=None) that will
446 raise a failure exception if first != second with a useful human
447 readable error message for those types.
448 """
449 #
450 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
451 # and vice versa. I opted for the conservative approach in case
452 # subclasses are not intended to be compared in detail to their super
453 # class instances using a type equality func. This means testing
454 # subtypes won't automagically use the detailed comparison. Callers
455 # should use their type specific assertSpamEqual method to compare
456 # subclasses if the detailed comparison is desired and appropriate.
457 # See the discussion in http://bugs.python.org/issue2578.
458 #
459 if type(first) is type(second):
460 asserter = self._type_equality_funcs.get(type(first))
461 if asserter is not None:
Benjamin Petersond46430b2009-11-29 22:26:26 +0000462 return asserter
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000463
464 return self._baseAssertEqual
465
466 def _baseAssertEqual(self, first, second, msg=None):
467 """The default assertEqual implementation, not type specific."""
468 if not first == second:
Michael Foord225a0992010-02-18 20:30:09 +0000469 standardMsg = '%s != %s' % (safe_repr(first), safe_repr(second))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000470 msg = self._formatMessage(msg, standardMsg)
471 raise self.failureException(msg)
472
473 def assertEqual(self, first, second, msg=None):
474 """Fail if the two objects are unequal as determined by the '=='
475 operator.
476 """
477 assertion_func = self._getAssertEqualityFunc(first, second)
478 assertion_func(first, second, msg=msg)
479
480 def assertNotEqual(self, first, second, msg=None):
481 """Fail if the two objects are equal as determined by the '=='
482 operator.
483 """
484 if not first != second:
Michael Foord225a0992010-02-18 20:30:09 +0000485 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
486 safe_repr(second)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000487 raise self.failureException(msg)
488
489 def assertAlmostEqual(self, first, second, places=7, msg=None):
490 """Fail if the two objects are unequal as determined by their
491 difference rounded to the given number of decimal places
492 (default 7) and comparing to zero.
493
494 Note that decimal places (from zero) are usually not the same
495 as significant digits (measured from the most signficant digit).
Michael Foordc3f79372009-09-13 16:40:02 +0000496
497 If the two objects compare equal then they will automatically
498 compare almost equal.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000499 """
Michael Foordc3f79372009-09-13 16:40:02 +0000500 if first == second:
Michael Foord225a0992010-02-18 20:30:09 +0000501 # shortcut for inf
Michael Foordc3f79372009-09-13 16:40:02 +0000502 return
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000503 if round(abs(second-first), places) != 0:
Michael Foord225a0992010-02-18 20:30:09 +0000504 standardMsg = '%s != %s within %r places' % (safe_repr(first),
505 safe_repr(second),
506 places)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000507 msg = self._formatMessage(msg, standardMsg)
508 raise self.failureException(msg)
509
510 def assertNotAlmostEqual(self, first, second, places=7, msg=None):
511 """Fail if the two objects are equal as determined by their
512 difference rounded to the given number of decimal places
513 (default 7) and comparing to zero.
514
515 Note that decimal places (from zero) are usually not the same
516 as significant digits (measured from the most signficant digit).
Michael Foordc3f79372009-09-13 16:40:02 +0000517
518 Objects that are equal automatically fail.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000519 """
Michael Foordc3f79372009-09-13 16:40:02 +0000520 if (first == second) or round(abs(second-first), places) == 0:
Michael Foord225a0992010-02-18 20:30:09 +0000521 standardMsg = '%s == %s within %r places' % (safe_repr(first),
522 safe_repr(second),
523 places)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000524 msg = self._formatMessage(msg, standardMsg)
525 raise self.failureException(msg)
526
527 # Synonyms for assertion methods
528
529 # The plurals are undocumented. Keep them that way to discourage use.
530 # Do not add more. Do not remove.
531 # Going through a deprecation cycle on these would annoy many people.
532 assertEquals = assertEqual
533 assertNotEquals = assertNotEqual
534 assertAlmostEquals = assertAlmostEqual
535 assertNotAlmostEquals = assertNotAlmostEqual
Michael Foord67dfc772010-02-10 14:31:30 +0000536 assert_ = assertTrue
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000537
538 # These fail* assertion method names are pending deprecation and will
539 # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
540 def _deprecate(original_func):
541 def deprecated_func(*args, **kwargs):
542 warnings.warn(
543 'Please use {0} instead.'.format(original_func.__name__),
544 PendingDeprecationWarning, 2)
545 return original_func(*args, **kwargs)
546 return deprecated_func
547
548 failUnlessEqual = _deprecate(assertEqual)
549 failIfEqual = _deprecate(assertNotEqual)
550 failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
551 failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
552 failUnless = _deprecate(assertTrue)
553 failUnlessRaises = _deprecate(assertRaises)
554 failIf = _deprecate(assertFalse)
555
556 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
557 """An equality assertion for ordered sequences (like lists and tuples).
558
R. David Murray05b41712010-01-29 19:35:39 +0000559 For the purposes of this function, a valid ordered sequence type is one
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000560 which can be indexed, has a length, and has an equality operator.
561
562 Args:
563 seq1: The first sequence to compare.
564 seq2: The second sequence to compare.
565 seq_type: The expected datatype of the sequences, or None if no
566 datatype should be enforced.
567 msg: Optional message to use on failure instead of a list of
568 differences.
569 """
570 if seq_type != None:
571 seq_type_name = seq_type.__name__
572 if not isinstance(seq1, seq_type):
Michael Foord225a0992010-02-18 20:30:09 +0000573 raise self.failureException('First sequence is not a %s: %s'
574 % (seq_type_name, safe_repr(seq1)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000575 if not isinstance(seq2, seq_type):
Michael Foord225a0992010-02-18 20:30:09 +0000576 raise self.failureException('Second sequence is not a %s: %s'
577 % (seq_type_name, safe_repr(seq2)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000578 else:
579 seq_type_name = "sequence"
580
581 differing = None
582 try:
583 len1 = len(seq1)
584 except (TypeError, NotImplementedError):
585 differing = 'First %s has no length. Non-sequence?' % (
586 seq_type_name)
587
588 if differing is None:
589 try:
590 len2 = len(seq2)
591 except (TypeError, NotImplementedError):
592 differing = 'Second %s has no length. Non-sequence?' % (
593 seq_type_name)
594
595 if differing is None:
596 if seq1 == seq2:
597 return
598
Michael Foord225a0992010-02-18 20:30:09 +0000599 seq1_repr = safe_repr(seq1)
600 seq2_repr = safe_repr(seq2)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000601 if len(seq1_repr) > 30:
602 seq1_repr = seq1_repr[:30] + '...'
603 if len(seq2_repr) > 30:
604 seq2_repr = seq2_repr[:30] + '...'
605 elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
606 differing = '%ss differ: %s != %s\n' % elements
607
608 for i in xrange(min(len1, len2)):
609 try:
610 item1 = seq1[i]
611 except (TypeError, IndexError, NotImplementedError):
612 differing += ('\nUnable to index element %d of first %s\n' %
613 (i, seq_type_name))
614 break
615
616 try:
617 item2 = seq2[i]
618 except (TypeError, IndexError, NotImplementedError):
619 differing += ('\nUnable to index element %d of second %s\n' %
620 (i, seq_type_name))
621 break
622
623 if item1 != item2:
624 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
625 (i, item1, item2))
626 break
627 else:
628 if (len1 == len2 and seq_type is None and
629 type(seq1) != type(seq2)):
630 # The sequences are the same, but have differing types.
631 return
632
633 if len1 > len2:
634 differing += ('\nFirst %s contains %d additional '
635 'elements.\n' % (seq_type_name, len1 - len2))
636 try:
637 differing += ('First extra element %d:\n%s\n' %
638 (len2, seq1[len2]))
639 except (TypeError, IndexError, NotImplementedError):
640 differing += ('Unable to index element %d '
641 'of first %s\n' % (len2, seq_type_name))
642 elif len1 < len2:
643 differing += ('\nSecond %s contains %d additional '
644 'elements.\n' % (seq_type_name, len2 - len1))
645 try:
646 differing += ('First extra element %d:\n%s\n' %
647 (len1, seq2[len1]))
648 except (TypeError, IndexError, NotImplementedError):
649 differing += ('Unable to index element %d '
650 'of second %s\n' % (len1, seq_type_name))
Georg Brandl46cc46a2009-10-01 20:11:14 +0000651 standardMsg = differing + '\n' + '\n'.join(
652 difflib.ndiff(pprint.pformat(seq1).splitlines(),
653 pprint.pformat(seq2).splitlines()))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000654 msg = self._formatMessage(msg, standardMsg)
655 self.fail(msg)
656
657 def assertListEqual(self, list1, list2, msg=None):
658 """A list-specific equality assertion.
659
660 Args:
661 list1: The first list to compare.
662 list2: The second list to compare.
663 msg: Optional message to use on failure instead of a list of
664 differences.
665
666 """
667 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
668
669 def assertTupleEqual(self, tuple1, tuple2, msg=None):
670 """A tuple-specific equality assertion.
671
672 Args:
673 tuple1: The first tuple to compare.
674 tuple2: The second tuple to compare.
675 msg: Optional message to use on failure instead of a list of
676 differences.
677 """
678 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
679
680 def assertSetEqual(self, set1, set2, msg=None):
681 """A set-specific equality assertion.
682
683 Args:
684 set1: The first set to compare.
685 set2: The second set to compare.
686 msg: Optional message to use on failure instead of a list of
687 differences.
688
689 For more general containership equality, assertSameElements will work
690 with things other than sets. This uses ducktyping to support
691 different types of sets, and is optimized for sets specifically
692 (parameters must support a difference method).
693 """
694 try:
695 difference1 = set1.difference(set2)
696 except TypeError, e:
697 self.fail('invalid type when attempting set difference: %s' % e)
698 except AttributeError, e:
699 self.fail('first argument does not support set difference: %s' % e)
700
701 try:
702 difference2 = set2.difference(set1)
703 except TypeError, e:
704 self.fail('invalid type when attempting set difference: %s' % e)
705 except AttributeError, e:
706 self.fail('second argument does not support set difference: %s' % e)
707
708 if not (difference1 or difference2):
709 return
710
711 lines = []
712 if difference1:
713 lines.append('Items in the first set but not the second:')
714 for item in difference1:
715 lines.append(repr(item))
716 if difference2:
717 lines.append('Items in the second set but not the first:')
718 for item in difference2:
719 lines.append(repr(item))
720
721 standardMsg = '\n'.join(lines)
722 self.fail(self._formatMessage(msg, standardMsg))
723
724 def assertIn(self, member, container, msg=None):
725 """Just like self.assertTrue(a in b), but with a nicer default message."""
726 if member not in container:
Michael Foord225a0992010-02-18 20:30:09 +0000727 standardMsg = '%s not found in %s' % (safe_repr(member),
728 safe_repr(container))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000729 self.fail(self._formatMessage(msg, standardMsg))
730
731 def assertNotIn(self, member, container, msg=None):
732 """Just like self.assertTrue(a not in b), but with a nicer default message."""
733 if member in container:
Michael Foord225a0992010-02-18 20:30:09 +0000734 standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
735 safe_repr(container))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000736 self.fail(self._formatMessage(msg, standardMsg))
737
738 def assertIs(self, expr1, expr2, msg=None):
739 """Just like self.assertTrue(a is b), but with a nicer default message."""
740 if expr1 is not expr2:
Michael Foord225a0992010-02-18 20:30:09 +0000741 standardMsg = '%s is not %s' % (safe_repr(expr1),
Michael Foordc2294dd2010-02-18 21:37:07 +0000742 safe_repr(expr2))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000743 self.fail(self._formatMessage(msg, standardMsg))
744
745 def assertIsNot(self, expr1, expr2, msg=None):
746 """Just like self.assertTrue(a is not b), but with a nicer default message."""
747 if expr1 is expr2:
Michael Foord225a0992010-02-18 20:30:09 +0000748 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000749 self.fail(self._formatMessage(msg, standardMsg))
750
751 def assertDictEqual(self, d1, d2, msg=None):
752 self.assert_(isinstance(d1, dict), 'First argument is not a dictionary')
753 self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary')
754
755 if d1 != d2:
756 standardMsg = ('\n' + '\n'.join(difflib.ndiff(
757 pprint.pformat(d1).splitlines(),
758 pprint.pformat(d2).splitlines())))
759 self.fail(self._formatMessage(msg, standardMsg))
760
761 def assertDictContainsSubset(self, expected, actual, msg=None):
762 """Checks whether actual is a superset of expected."""
763 missing = []
764 mismatched = []
765 for key, value in expected.iteritems():
766 if key not in actual:
767 missing.append(key)
768 elif value != actual[key]:
Georg Brandl46cc46a2009-10-01 20:11:14 +0000769 mismatched.append('%s, expected: %s, actual: %s' %
Michael Foordc2294dd2010-02-18 21:37:07 +0000770 (safe_repr(key), safe_repr(value),
771 safe_repr(actual[key])))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000772
773 if not (missing or mismatched):
774 return
775
776 standardMsg = ''
777 if missing:
Michael Foord225a0992010-02-18 20:30:09 +0000778 standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
779 missing)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000780 if mismatched:
781 if standardMsg:
782 standardMsg += '; '
783 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
784
785 self.fail(self._formatMessage(msg, standardMsg))
786
787 def assertSameElements(self, expected_seq, actual_seq, msg=None):
788 """An unordered sequence specific comparison.
789
790 Raises with an error message listing which elements of expected_seq
791 are missing from actual_seq and vice versa if any.
Michael Foordd0edec32010-02-05 22:55:09 +0000792
793 Duplicate elements are ignored when comparing *expected_seq* and
794 *actual_seq*. It is the equivalent of ``assertEqual(set(expected),
795 set(actual))`` but it works with sequences of unhashable objects as
796 well.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000797 """
Florent Xicluna1f3b4e12010-03-07 12:14:25 +0000798 with warnings.catch_warnings():
799 if sys.py3kwarning:
800 # Silence Py3k warning raised during the sorting
801 for msg in ["dict inequality comparisons",
802 "builtin_function_or_method order comparisons",
803 "comparing unequal types"]:
804 warnings.filterwarnings("ignore", msg, DeprecationWarning)
805 try:
806 expected = set(expected_seq)
807 actual = set(actual_seq)
808 missing = sorted(expected.difference(actual))
809 unexpected = sorted(actual.difference(expected))
810 except TypeError:
811 # Fall back to slower list-compare if any of the objects are
812 # not hashable.
813 expected = sorted(expected_seq)
814 actual = sorted(actual_seq)
Michael Foord225a0992010-02-18 20:30:09 +0000815 missing, unexpected = sorted_list_difference(expected, actual)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000816 errors = []
817 if missing:
Michael Foord225a0992010-02-18 20:30:09 +0000818 errors.append('Expected, but missing:\n %s' %
819 safe_repr(missing))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000820 if unexpected:
Michael Foord225a0992010-02-18 20:30:09 +0000821 errors.append('Unexpected, but present:\n %s' %
822 safe_repr(unexpected))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000823 if errors:
824 standardMsg = '\n'.join(errors)
825 self.fail(self._formatMessage(msg, standardMsg))
826
827 def assertMultiLineEqual(self, first, second, msg=None):
828 """Assert that two multi-line strings are equal."""
829 self.assert_(isinstance(first, basestring), (
830 'First argument is not a string'))
831 self.assert_(isinstance(second, basestring), (
832 'Second argument is not a string'))
833
834 if first != second:
Georg Brandl46cc46a2009-10-01 20:11:14 +0000835 standardMsg = '\n' + ''.join(difflib.ndiff(first.splitlines(True),
836 second.splitlines(True)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000837 self.fail(self._formatMessage(msg, standardMsg))
838
839 def assertLess(self, a, b, msg=None):
840 """Just like self.assertTrue(a < b), but with a nicer default message."""
841 if not a < b:
Michael Foord225a0992010-02-18 20:30:09 +0000842 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000843 self.fail(self._formatMessage(msg, standardMsg))
844
845 def assertLessEqual(self, a, b, msg=None):
846 """Just like self.assertTrue(a <= b), but with a nicer default message."""
847 if not a <= b:
Michael Foord225a0992010-02-18 20:30:09 +0000848 standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000849 self.fail(self._formatMessage(msg, standardMsg))
850
851 def assertGreater(self, a, b, msg=None):
852 """Just like self.assertTrue(a > b), but with a nicer default message."""
853 if not a > b:
Michael Foord225a0992010-02-18 20:30:09 +0000854 standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000855 self.fail(self._formatMessage(msg, standardMsg))
856
857 def assertGreaterEqual(self, a, b, msg=None):
858 """Just like self.assertTrue(a >= b), but with a nicer default message."""
859 if not a >= b:
Michael Foord225a0992010-02-18 20:30:09 +0000860 standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000861 self.fail(self._formatMessage(msg, standardMsg))
862
863 def assertIsNone(self, obj, msg=None):
864 """Same as self.assertTrue(obj is None), with a nicer default message."""
865 if obj is not None:
Michael Foord225a0992010-02-18 20:30:09 +0000866 standardMsg = '%s is not None' % (safe_repr(obj),)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000867 self.fail(self._formatMessage(msg, standardMsg))
868
869 def assertIsNotNone(self, obj, msg=None):
870 """Included for symmetry with assertIsNone."""
871 if obj is None:
872 standardMsg = 'unexpectedly None'
873 self.fail(self._formatMessage(msg, standardMsg))
874
Georg Brandlf895cf52009-10-01 20:59:31 +0000875 def assertIsInstance(self, obj, cls, msg=None):
876 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
877 default message."""
878 if not isinstance(obj, cls):
Michael Foord225a0992010-02-18 20:30:09 +0000879 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
Georg Brandlf895cf52009-10-01 20:59:31 +0000880 self.fail(self._formatMessage(msg, standardMsg))
881
882 def assertNotIsInstance(self, obj, cls, msg=None):
883 """Included for symmetry with assertIsInstance."""
884 if isinstance(obj, cls):
Michael Foord225a0992010-02-18 20:30:09 +0000885 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
Georg Brandlf895cf52009-10-01 20:59:31 +0000886 self.fail(self._formatMessage(msg, standardMsg))
887
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000888 def assertRaisesRegexp(self, expected_exception, expected_regexp,
889 callable_obj=None, *args, **kwargs):
890 """Asserts that the message in a raised exception matches a regexp.
891
892 Args:
893 expected_exception: Exception class expected to be raised.
894 expected_regexp: Regexp (re pattern object or string) expected
895 to be found in error message.
896 callable_obj: Function to be called.
897 args: Extra args.
898 kwargs: Extra kwargs.
899 """
900 context = _AssertRaisesContext(expected_exception, self, expected_regexp)
901 if callable_obj is None:
902 return context
903 with context:
904 callable_obj(*args, **kwargs)
905
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000906 def assertRegexpMatches(self, text, expected_regexp, msg=None):
907 if isinstance(expected_regexp, basestring):
908 expected_regexp = re.compile(expected_regexp)
909 if not expected_regexp.search(text):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000910 msg = msg or "Regexp didn't match"
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000911 msg = '%s: %r not found in %r' % (msg, expected_regexp.pattern, text)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000912 raise self.failureException(msg)
913
914
915class FunctionTestCase(TestCase):
916 """A test case that wraps a test function.
917
918 This is useful for slipping pre-existing test functions into the
919 unittest framework. Optionally, set-up and tidy-up functions can be
920 supplied. As with TestCase, the tidy-up ('tearDown') function will
921 always be called if the set-up ('setUp') function ran successfully.
922 """
923
924 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
925 super(FunctionTestCase, self).__init__()
926 self._setUpFunc = setUp
927 self._tearDownFunc = tearDown
928 self._testFunc = testFunc
929 self._description = description
930
931 def setUp(self):
932 if self._setUpFunc is not None:
933 self._setUpFunc()
934
935 def tearDown(self):
936 if self._tearDownFunc is not None:
937 self._tearDownFunc()
938
939 def runTest(self):
940 self._testFunc()
941
942 def id(self):
943 return self._testFunc.__name__
944
945 def __eq__(self, other):
946 if not isinstance(other, self.__class__):
947 return NotImplemented
948
949 return self._setUpFunc == other._setUpFunc and \
950 self._tearDownFunc == other._tearDownFunc and \
951 self._testFunc == other._testFunc and \
952 self._description == other._description
953
954 def __ne__(self, other):
955 return not self == other
956
957 def __hash__(self):
958 return hash((type(self), self._setUpFunc, self._tearDownFunc,
959 self._testFunc, self._description))
960
961 def __str__(self):
Michael Foord225a0992010-02-18 20:30:09 +0000962 return "%s (%s)" % (strclass(self.__class__),
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000963 self._testFunc.__name__)
964
965 def __repr__(self):
Michael Foord225a0992010-02-18 20:30:09 +0000966 return "<%s tec=%s>" % (strclass(self.__class__),
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000967 self._testFunc)
968
969 def shortDescription(self):
970 if self._description is not None:
971 return self._description
972 doc = self._testFunc.__doc__
973 return doc and doc.split("\n")[0].strip() or None