blob: 19b196c86feef5e04a89b883797c118417d8a26a [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
156
157 def __init__(self, methodName='runTest'):
158 """Create an instance of the class that will use the named test
159 method when executed. Raises a ValueError if the instance does
160 not have a method with the specified name.
161 """
162 self._testMethodName = methodName
163 self._resultForDoCleanups = None
164 try:
165 testMethod = getattr(self, methodName)
166 except AttributeError:
Michael Foordc2294dd2010-02-18 21:37:07 +0000167 raise ValueError("no such test method in %s: %s" %
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000168 (self.__class__, methodName))
169 self._testMethodDoc = testMethod.__doc__
170 self._cleanups = []
171
172 # Map types to custom assertEqual functions that will compare
173 # instances of said type in more detail to generate a more useful
174 # error message.
175 self._type_equality_funcs = {}
176 self.addTypeEqualityFunc(dict, self.assertDictEqual)
177 self.addTypeEqualityFunc(list, self.assertListEqual)
178 self.addTypeEqualityFunc(tuple, self.assertTupleEqual)
179 self.addTypeEqualityFunc(set, self.assertSetEqual)
180 self.addTypeEqualityFunc(frozenset, self.assertSetEqual)
Michael Foordfe6349c2010-02-08 22:41:16 +0000181 self.addTypeEqualityFunc(unicode, self.assertMultiLineEqual)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000182
183 def addTypeEqualityFunc(self, typeobj, function):
184 """Add a type specific assertEqual style function to compare a type.
185
186 This method is for use by TestCase subclasses that need to register
187 their own type equality functions to provide nicer error messages.
188
189 Args:
190 typeobj: The data type to call this function on when both values
191 are of the same type in assertEqual().
192 function: The callable taking two arguments and an optional
193 msg= argument that raises self.failureException with a
194 useful error message when the two arguments are not equal.
195 """
Benjamin Petersond46430b2009-11-29 22:26:26 +0000196 self._type_equality_funcs[typeobj] = function
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000197
198 def addCleanup(self, function, *args, **kwargs):
199 """Add a function, with arguments, to be called when the test is
200 completed. Functions added are called on a LIFO basis and are
201 called after tearDown on test failure or success.
202
203 Cleanup items are called even if setUp fails (unlike tearDown)."""
204 self._cleanups.append((function, args, kwargs))
205
206 def setUp(self):
207 "Hook method for setting up the test fixture before exercising it."
208 pass
209
210 def tearDown(self):
211 "Hook method for deconstructing the test fixture after testing it."
212 pass
213
214 def countTestCases(self):
215 return 1
216
217 def defaultTestResult(self):
218 return result.TestResult()
219
220 def shortDescription(self):
Michael Foorddb43b5a2010-02-10 14:25:12 +0000221 """Returns a one-line description of the test, or None if no
222 description has been provided.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000223
Michael Foorddb43b5a2010-02-10 14:25:12 +0000224 The default implementation of this method returns the first line of
225 the specified test method's docstring.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000226 """
Michael Foorddb43b5a2010-02-10 14:25:12 +0000227 doc = self._testMethodDoc
228 return doc and doc.split("\n")[0].strip() or None
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000229
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000230
231 def id(self):
Michael Foord225a0992010-02-18 20:30:09 +0000232 return "%s.%s" % (strclass(self.__class__), self._testMethodName)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000233
234 def __eq__(self, other):
235 if type(self) is not type(other):
236 return NotImplemented
237
238 return self._testMethodName == other._testMethodName
239
240 def __ne__(self, other):
241 return not self == other
242
243 def __hash__(self):
244 return hash((type(self), self._testMethodName))
245
246 def __str__(self):
Michael Foord225a0992010-02-18 20:30:09 +0000247 return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000248
249 def __repr__(self):
250 return "<%s testMethod=%s>" % \
Michael Foord225a0992010-02-18 20:30:09 +0000251 (strclass(self.__class__), self._testMethodName)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000252
Michael Foordae3db0a2010-02-22 23:28:32 +0000253 def _addSkip(self, result, reason):
254 addSkip = getattr(result, 'addSkip', None)
255 if addSkip is not None:
256 addSkip(self, reason)
257 else:
258 warnings.warn("TestResult has no addSkip method, skips not reported",
259 RuntimeWarning, 2)
260 result.addSuccess(self)
261
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000262 def run(self, result=None):
263 orig_result = result
264 if result is None:
265 result = self.defaultTestResult()
266 startTestRun = getattr(result, 'startTestRun', None)
267 if startTestRun is not None:
268 startTestRun()
269
270 self._resultForDoCleanups = result
271 result.startTest(self)
Michael Foord53e8eea2010-03-07 20:22:12 +0000272
273 testMethod = getattr(self, self._testMethodName)
274 if (getattr(self.__class__, "__unittest_skip__", False) or
275 getattr(testMethod, "__unittest_skip__", False)):
276 # If the class or method was skipped.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000277 try:
Michael Foord53e8eea2010-03-07 20:22:12 +0000278 skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
279 or getattr(testMethod, '__unittest_skip_why__', ''))
280 self._addSkip(result, skip_why)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000281 finally:
282 result.stopTest(self)
283 return
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000284 try:
285 success = False
286 try:
287 self.setUp()
288 except SkipTest as e:
Michael Foordae3db0a2010-02-22 23:28:32 +0000289 self._addSkip(result, str(e))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000290 except Exception:
291 result.addError(self, sys.exc_info())
292 else:
293 try:
294 testMethod()
295 except self.failureException:
296 result.addFailure(self, sys.exc_info())
297 except _ExpectedFailure as e:
Michael Foordae3db0a2010-02-22 23:28:32 +0000298 addExpectedFailure = getattr(result, 'addExpectedFailure', None)
299 if addExpectedFailure is not None:
300 addExpectedFailure(self, e.exc_info)
301 else:
302 warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
303 RuntimeWarning)
304 result.addSuccess(self)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000305 except _UnexpectedSuccess:
Michael Foordae3db0a2010-02-22 23:28:32 +0000306 addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
307 if addUnexpectedSuccess is not None:
308 addUnexpectedSuccess(self)
309 else:
310 warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures",
311 RuntimeWarning)
312 result.addFailure(self, sys.exc_info())
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000313 except SkipTest as e:
Michael Foordae3db0a2010-02-22 23:28:32 +0000314 self._addSkip(result, str(e))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000315 except Exception:
316 result.addError(self, sys.exc_info())
317 else:
318 success = True
319
320 try:
321 self.tearDown()
322 except Exception:
323 result.addError(self, sys.exc_info())
324 success = False
325
326 cleanUpSuccess = self.doCleanups()
327 success = success and cleanUpSuccess
328 if success:
329 result.addSuccess(self)
330 finally:
331 result.stopTest(self)
332 if orig_result is None:
333 stopTestRun = getattr(result, 'stopTestRun', None)
334 if stopTestRun is not None:
335 stopTestRun()
336
337 def doCleanups(self):
338 """Execute all cleanup functions. Normally called for you after
339 tearDown."""
340 result = self._resultForDoCleanups
341 ok = True
342 while self._cleanups:
343 function, args, kwargs = self._cleanups.pop(-1)
344 try:
345 function(*args, **kwargs)
346 except Exception:
347 ok = False
348 result.addError(self, sys.exc_info())
349 return ok
350
351 def __call__(self, *args, **kwds):
352 return self.run(*args, **kwds)
353
354 def debug(self):
355 """Run the test without collecting errors in a TestResult"""
356 self.setUp()
357 getattr(self, self._testMethodName)()
358 self.tearDown()
359
360 def skipTest(self, reason):
361 """Skip this test."""
362 raise SkipTest(reason)
363
364 def fail(self, msg=None):
365 """Fail immediately, with the given message."""
366 raise self.failureException(msg)
367
368 def assertFalse(self, expr, msg=None):
369 "Fail the test if the expression is true."
370 if expr:
Michael Foord225a0992010-02-18 20:30:09 +0000371 msg = self._formatMessage(msg, "%s is not False" % safe_repr(expr))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000372 raise self.failureException(msg)
373
374 def assertTrue(self, expr, msg=None):
375 """Fail the test unless the expression is true."""
376 if not expr:
Michael Foord225a0992010-02-18 20:30:09 +0000377 msg = self._formatMessage(msg, "%s is not True" % safe_repr(expr))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000378 raise self.failureException(msg)
379
380 def _formatMessage(self, msg, standardMsg):
381 """Honour the longMessage attribute when generating failure messages.
382 If longMessage is False this means:
383 * Use only an explicit message if it is provided
384 * Otherwise use the standard message for the assert
385
386 If longMessage is True:
387 * Use the standard message
388 * If an explicit message is provided, plus ' : ' and the explicit message
389 """
390 if not self.longMessage:
391 return msg or standardMsg
392 if msg is None:
393 return standardMsg
Michael Foord53e8eea2010-03-07 20:22:12 +0000394 try:
395 # don't switch to '{}' formatting in Python 2.X
396 # it changes the way unicode input is handled
397 return '%s : %s' % (standardMsg, msg)
398 except UnicodeDecodeError:
399 return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000400
401
402 def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
403 """Fail unless an exception of class excClass is thrown
404 by callableObj when invoked with arguments args and keyword
405 arguments kwargs. If a different type of exception is
406 thrown, it will not be caught, and the test case will be
407 deemed to have suffered an error, exactly as for an
408 unexpected exception.
409
410 If called with callableObj omitted or None, will return a
411 context object used like this::
412
Michael Foordd0edec32010-02-05 22:55:09 +0000413 with self.assertRaises(SomeException):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000414 do_something()
Michael Foordd0edec32010-02-05 22:55:09 +0000415
416 The context manager keeps a reference to the exception as
Ezio Melotticd4f6572010-02-08 21:52:08 +0000417 the 'exception' attribute. This allows you to inspect the
Michael Foordd0edec32010-02-05 22:55:09 +0000418 exception after the assertion::
419
420 with self.assertRaises(SomeException) as cm:
421 do_something()
Georg Brandldc3694b2010-02-07 17:02:22 +0000422 the_exception = cm.exception
Michael Foord757cc4d2010-02-05 23:22:37 +0000423 self.assertEqual(the_exception.error_code, 3)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000424 """
425 context = _AssertRaisesContext(excClass, self)
426 if callableObj is None:
427 return context
428 with context:
429 callableObj(*args, **kwargs)
430
431 def _getAssertEqualityFunc(self, first, second):
432 """Get a detailed comparison function for the types of the two args.
433
434 Returns: A callable accepting (first, second, msg=None) that will
435 raise a failure exception if first != second with a useful human
436 readable error message for those types.
437 """
438 #
439 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
440 # and vice versa. I opted for the conservative approach in case
441 # subclasses are not intended to be compared in detail to their super
442 # class instances using a type equality func. This means testing
443 # subtypes won't automagically use the detailed comparison. Callers
444 # should use their type specific assertSpamEqual method to compare
445 # subclasses if the detailed comparison is desired and appropriate.
446 # See the discussion in http://bugs.python.org/issue2578.
447 #
448 if type(first) is type(second):
449 asserter = self._type_equality_funcs.get(type(first))
450 if asserter is not None:
Benjamin Petersond46430b2009-11-29 22:26:26 +0000451 return asserter
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000452
453 return self._baseAssertEqual
454
455 def _baseAssertEqual(self, first, second, msg=None):
456 """The default assertEqual implementation, not type specific."""
457 if not first == second:
Michael Foord225a0992010-02-18 20:30:09 +0000458 standardMsg = '%s != %s' % (safe_repr(first), safe_repr(second))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000459 msg = self._formatMessage(msg, standardMsg)
460 raise self.failureException(msg)
461
462 def assertEqual(self, first, second, msg=None):
463 """Fail if the two objects are unequal as determined by the '=='
464 operator.
465 """
466 assertion_func = self._getAssertEqualityFunc(first, second)
467 assertion_func(first, second, msg=msg)
468
469 def assertNotEqual(self, first, second, msg=None):
470 """Fail if the two objects are equal as determined by the '=='
471 operator.
472 """
473 if not first != second:
Michael Foord225a0992010-02-18 20:30:09 +0000474 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
475 safe_repr(second)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000476 raise self.failureException(msg)
477
478 def assertAlmostEqual(self, first, second, places=7, msg=None):
479 """Fail if the two objects are unequal as determined by their
480 difference rounded to the given number of decimal places
481 (default 7) and comparing to zero.
482
483 Note that decimal places (from zero) are usually not the same
484 as significant digits (measured from the most signficant digit).
Michael Foordc3f79372009-09-13 16:40:02 +0000485
486 If the two objects compare equal then they will automatically
487 compare almost equal.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000488 """
Michael Foordc3f79372009-09-13 16:40:02 +0000489 if first == second:
Michael Foord225a0992010-02-18 20:30:09 +0000490 # shortcut for inf
Michael Foordc3f79372009-09-13 16:40:02 +0000491 return
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000492 if round(abs(second-first), places) != 0:
Michael Foord225a0992010-02-18 20:30:09 +0000493 standardMsg = '%s != %s within %r places' % (safe_repr(first),
494 safe_repr(second),
495 places)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000496 msg = self._formatMessage(msg, standardMsg)
497 raise self.failureException(msg)
498
499 def assertNotAlmostEqual(self, first, second, places=7, msg=None):
500 """Fail if the two objects are equal as determined by their
501 difference rounded to the given number of decimal places
502 (default 7) and comparing to zero.
503
504 Note that decimal places (from zero) are usually not the same
505 as significant digits (measured from the most signficant digit).
Michael Foordc3f79372009-09-13 16:40:02 +0000506
507 Objects that are equal automatically fail.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000508 """
Michael Foordc3f79372009-09-13 16:40:02 +0000509 if (first == second) or round(abs(second-first), places) == 0:
Michael Foord225a0992010-02-18 20:30:09 +0000510 standardMsg = '%s == %s within %r places' % (safe_repr(first),
511 safe_repr(second),
512 places)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000513 msg = self._formatMessage(msg, standardMsg)
514 raise self.failureException(msg)
515
516 # Synonyms for assertion methods
517
518 # The plurals are undocumented. Keep them that way to discourage use.
519 # Do not add more. Do not remove.
520 # Going through a deprecation cycle on these would annoy many people.
521 assertEquals = assertEqual
522 assertNotEquals = assertNotEqual
523 assertAlmostEquals = assertAlmostEqual
524 assertNotAlmostEquals = assertNotAlmostEqual
Michael Foord67dfc772010-02-10 14:31:30 +0000525 assert_ = assertTrue
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000526
527 # These fail* assertion method names are pending deprecation and will
528 # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
529 def _deprecate(original_func):
530 def deprecated_func(*args, **kwargs):
531 warnings.warn(
532 'Please use {0} instead.'.format(original_func.__name__),
533 PendingDeprecationWarning, 2)
534 return original_func(*args, **kwargs)
535 return deprecated_func
536
537 failUnlessEqual = _deprecate(assertEqual)
538 failIfEqual = _deprecate(assertNotEqual)
539 failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
540 failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
541 failUnless = _deprecate(assertTrue)
542 failUnlessRaises = _deprecate(assertRaises)
543 failIf = _deprecate(assertFalse)
544
545 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
546 """An equality assertion for ordered sequences (like lists and tuples).
547
R. David Murray05b41712010-01-29 19:35:39 +0000548 For the purposes of this function, a valid ordered sequence type is one
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000549 which can be indexed, has a length, and has an equality operator.
550
551 Args:
552 seq1: The first sequence to compare.
553 seq2: The second sequence to compare.
554 seq_type: The expected datatype of the sequences, or None if no
555 datatype should be enforced.
556 msg: Optional message to use on failure instead of a list of
557 differences.
558 """
559 if seq_type != None:
560 seq_type_name = seq_type.__name__
561 if not isinstance(seq1, seq_type):
Michael Foord225a0992010-02-18 20:30:09 +0000562 raise self.failureException('First sequence is not a %s: %s'
563 % (seq_type_name, safe_repr(seq1)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000564 if not isinstance(seq2, seq_type):
Michael Foord225a0992010-02-18 20:30:09 +0000565 raise self.failureException('Second sequence is not a %s: %s'
566 % (seq_type_name, safe_repr(seq2)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000567 else:
568 seq_type_name = "sequence"
569
570 differing = None
571 try:
572 len1 = len(seq1)
573 except (TypeError, NotImplementedError):
574 differing = 'First %s has no length. Non-sequence?' % (
575 seq_type_name)
576
577 if differing is None:
578 try:
579 len2 = len(seq2)
580 except (TypeError, NotImplementedError):
581 differing = 'Second %s has no length. Non-sequence?' % (
582 seq_type_name)
583
584 if differing is None:
585 if seq1 == seq2:
586 return
587
Michael Foord225a0992010-02-18 20:30:09 +0000588 seq1_repr = safe_repr(seq1)
589 seq2_repr = safe_repr(seq2)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000590 if len(seq1_repr) > 30:
591 seq1_repr = seq1_repr[:30] + '...'
592 if len(seq2_repr) > 30:
593 seq2_repr = seq2_repr[:30] + '...'
594 elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
595 differing = '%ss differ: %s != %s\n' % elements
596
597 for i in xrange(min(len1, len2)):
598 try:
599 item1 = seq1[i]
600 except (TypeError, IndexError, NotImplementedError):
601 differing += ('\nUnable to index element %d of first %s\n' %
602 (i, seq_type_name))
603 break
604
605 try:
606 item2 = seq2[i]
607 except (TypeError, IndexError, NotImplementedError):
608 differing += ('\nUnable to index element %d of second %s\n' %
609 (i, seq_type_name))
610 break
611
612 if item1 != item2:
613 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
614 (i, item1, item2))
615 break
616 else:
617 if (len1 == len2 and seq_type is None and
618 type(seq1) != type(seq2)):
619 # The sequences are the same, but have differing types.
620 return
621
622 if len1 > len2:
623 differing += ('\nFirst %s contains %d additional '
624 'elements.\n' % (seq_type_name, len1 - len2))
625 try:
626 differing += ('First extra element %d:\n%s\n' %
627 (len2, seq1[len2]))
628 except (TypeError, IndexError, NotImplementedError):
629 differing += ('Unable to index element %d '
630 'of first %s\n' % (len2, seq_type_name))
631 elif len1 < len2:
632 differing += ('\nSecond %s contains %d additional '
633 'elements.\n' % (seq_type_name, len2 - len1))
634 try:
635 differing += ('First extra element %d:\n%s\n' %
636 (len1, seq2[len1]))
637 except (TypeError, IndexError, NotImplementedError):
638 differing += ('Unable to index element %d '
639 'of second %s\n' % (len1, seq_type_name))
Georg Brandl46cc46a2009-10-01 20:11:14 +0000640 standardMsg = differing + '\n' + '\n'.join(
641 difflib.ndiff(pprint.pformat(seq1).splitlines(),
642 pprint.pformat(seq2).splitlines()))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000643 msg = self._formatMessage(msg, standardMsg)
644 self.fail(msg)
645
646 def assertListEqual(self, list1, list2, msg=None):
647 """A list-specific equality assertion.
648
649 Args:
650 list1: The first list to compare.
651 list2: The second list to compare.
652 msg: Optional message to use on failure instead of a list of
653 differences.
654
655 """
656 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
657
658 def assertTupleEqual(self, tuple1, tuple2, msg=None):
659 """A tuple-specific equality assertion.
660
661 Args:
662 tuple1: The first tuple to compare.
663 tuple2: The second tuple to compare.
664 msg: Optional message to use on failure instead of a list of
665 differences.
666 """
667 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
668
669 def assertSetEqual(self, set1, set2, msg=None):
670 """A set-specific equality assertion.
671
672 Args:
673 set1: The first set to compare.
674 set2: The second set to compare.
675 msg: Optional message to use on failure instead of a list of
676 differences.
677
678 For more general containership equality, assertSameElements will work
679 with things other than sets. This uses ducktyping to support
680 different types of sets, and is optimized for sets specifically
681 (parameters must support a difference method).
682 """
683 try:
684 difference1 = set1.difference(set2)
685 except TypeError, e:
686 self.fail('invalid type when attempting set difference: %s' % e)
687 except AttributeError, e:
688 self.fail('first argument does not support set difference: %s' % e)
689
690 try:
691 difference2 = set2.difference(set1)
692 except TypeError, e:
693 self.fail('invalid type when attempting set difference: %s' % e)
694 except AttributeError, e:
695 self.fail('second argument does not support set difference: %s' % e)
696
697 if not (difference1 or difference2):
698 return
699
700 lines = []
701 if difference1:
702 lines.append('Items in the first set but not the second:')
703 for item in difference1:
704 lines.append(repr(item))
705 if difference2:
706 lines.append('Items in the second set but not the first:')
707 for item in difference2:
708 lines.append(repr(item))
709
710 standardMsg = '\n'.join(lines)
711 self.fail(self._formatMessage(msg, standardMsg))
712
713 def assertIn(self, member, container, msg=None):
714 """Just like self.assertTrue(a in b), but with a nicer default message."""
715 if member not in container:
Michael Foord225a0992010-02-18 20:30:09 +0000716 standardMsg = '%s not found in %s' % (safe_repr(member),
717 safe_repr(container))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000718 self.fail(self._formatMessage(msg, standardMsg))
719
720 def assertNotIn(self, member, container, msg=None):
721 """Just like self.assertTrue(a not in b), but with a nicer default message."""
722 if member in container:
Michael Foord225a0992010-02-18 20:30:09 +0000723 standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
724 safe_repr(container))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000725 self.fail(self._formatMessage(msg, standardMsg))
726
727 def assertIs(self, expr1, expr2, msg=None):
728 """Just like self.assertTrue(a is b), but with a nicer default message."""
729 if expr1 is not expr2:
Michael Foord225a0992010-02-18 20:30:09 +0000730 standardMsg = '%s is not %s' % (safe_repr(expr1),
Michael Foordc2294dd2010-02-18 21:37:07 +0000731 safe_repr(expr2))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000732 self.fail(self._formatMessage(msg, standardMsg))
733
734 def assertIsNot(self, expr1, expr2, msg=None):
735 """Just like self.assertTrue(a is not b), but with a nicer default message."""
736 if expr1 is expr2:
Michael Foord225a0992010-02-18 20:30:09 +0000737 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000738 self.fail(self._formatMessage(msg, standardMsg))
739
740 def assertDictEqual(self, d1, d2, msg=None):
741 self.assert_(isinstance(d1, dict), 'First argument is not a dictionary')
742 self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary')
743
744 if d1 != d2:
745 standardMsg = ('\n' + '\n'.join(difflib.ndiff(
746 pprint.pformat(d1).splitlines(),
747 pprint.pformat(d2).splitlines())))
748 self.fail(self._formatMessage(msg, standardMsg))
749
750 def assertDictContainsSubset(self, expected, actual, msg=None):
751 """Checks whether actual is a superset of expected."""
752 missing = []
753 mismatched = []
754 for key, value in expected.iteritems():
755 if key not in actual:
756 missing.append(key)
757 elif value != actual[key]:
Georg Brandl46cc46a2009-10-01 20:11:14 +0000758 mismatched.append('%s, expected: %s, actual: %s' %
Michael Foordc2294dd2010-02-18 21:37:07 +0000759 (safe_repr(key), safe_repr(value),
760 safe_repr(actual[key])))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000761
762 if not (missing or mismatched):
763 return
764
765 standardMsg = ''
766 if missing:
Michael Foord225a0992010-02-18 20:30:09 +0000767 standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
768 missing)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000769 if mismatched:
770 if standardMsg:
771 standardMsg += '; '
772 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
773
774 self.fail(self._formatMessage(msg, standardMsg))
775
776 def assertSameElements(self, expected_seq, actual_seq, msg=None):
777 """An unordered sequence specific comparison.
778
779 Raises with an error message listing which elements of expected_seq
780 are missing from actual_seq and vice versa if any.
Michael Foordd0edec32010-02-05 22:55:09 +0000781
782 Duplicate elements are ignored when comparing *expected_seq* and
783 *actual_seq*. It is the equivalent of ``assertEqual(set(expected),
784 set(actual))`` but it works with sequences of unhashable objects as
785 well.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000786 """
Florent Xicluna1f3b4e12010-03-07 12:14:25 +0000787 with warnings.catch_warnings():
788 if sys.py3kwarning:
789 # Silence Py3k warning raised during the sorting
790 for msg in ["dict inequality comparisons",
791 "builtin_function_or_method order comparisons",
792 "comparing unequal types"]:
793 warnings.filterwarnings("ignore", msg, DeprecationWarning)
794 try:
795 expected = set(expected_seq)
796 actual = set(actual_seq)
797 missing = sorted(expected.difference(actual))
798 unexpected = sorted(actual.difference(expected))
799 except TypeError:
800 # Fall back to slower list-compare if any of the objects are
801 # not hashable.
802 expected = sorted(expected_seq)
803 actual = sorted(actual_seq)
Michael Foord225a0992010-02-18 20:30:09 +0000804 missing, unexpected = sorted_list_difference(expected, actual)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000805 errors = []
806 if missing:
Michael Foord225a0992010-02-18 20:30:09 +0000807 errors.append('Expected, but missing:\n %s' %
808 safe_repr(missing))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000809 if unexpected:
Michael Foord225a0992010-02-18 20:30:09 +0000810 errors.append('Unexpected, but present:\n %s' %
811 safe_repr(unexpected))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000812 if errors:
813 standardMsg = '\n'.join(errors)
814 self.fail(self._formatMessage(msg, standardMsg))
815
816 def assertMultiLineEqual(self, first, second, msg=None):
817 """Assert that two multi-line strings are equal."""
818 self.assert_(isinstance(first, basestring), (
819 'First argument is not a string'))
820 self.assert_(isinstance(second, basestring), (
821 'Second argument is not a string'))
822
823 if first != second:
Georg Brandl46cc46a2009-10-01 20:11:14 +0000824 standardMsg = '\n' + ''.join(difflib.ndiff(first.splitlines(True),
825 second.splitlines(True)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000826 self.fail(self._formatMessage(msg, standardMsg))
827
828 def assertLess(self, a, b, msg=None):
829 """Just like self.assertTrue(a < b), but with a nicer default message."""
830 if not a < b:
Michael Foord225a0992010-02-18 20:30:09 +0000831 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000832 self.fail(self._formatMessage(msg, standardMsg))
833
834 def assertLessEqual(self, a, b, msg=None):
835 """Just like self.assertTrue(a <= b), but with a nicer default message."""
836 if not a <= b:
Michael Foord225a0992010-02-18 20:30:09 +0000837 standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000838 self.fail(self._formatMessage(msg, standardMsg))
839
840 def assertGreater(self, a, b, msg=None):
841 """Just like self.assertTrue(a > b), but with a nicer default message."""
842 if not a > b:
Michael Foord225a0992010-02-18 20:30:09 +0000843 standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000844 self.fail(self._formatMessage(msg, standardMsg))
845
846 def assertGreaterEqual(self, a, b, msg=None):
847 """Just like self.assertTrue(a >= b), but with a nicer default message."""
848 if not a >= b:
Michael Foord225a0992010-02-18 20:30:09 +0000849 standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000850 self.fail(self._formatMessage(msg, standardMsg))
851
852 def assertIsNone(self, obj, msg=None):
853 """Same as self.assertTrue(obj is None), with a nicer default message."""
854 if obj is not None:
Michael Foord225a0992010-02-18 20:30:09 +0000855 standardMsg = '%s is not None' % (safe_repr(obj),)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000856 self.fail(self._formatMessage(msg, standardMsg))
857
858 def assertIsNotNone(self, obj, msg=None):
859 """Included for symmetry with assertIsNone."""
860 if obj is None:
861 standardMsg = 'unexpectedly None'
862 self.fail(self._formatMessage(msg, standardMsg))
863
Georg Brandlf895cf52009-10-01 20:59:31 +0000864 def assertIsInstance(self, obj, cls, msg=None):
865 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
866 default message."""
867 if not isinstance(obj, cls):
Michael Foord225a0992010-02-18 20:30:09 +0000868 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
Georg Brandlf895cf52009-10-01 20:59:31 +0000869 self.fail(self._formatMessage(msg, standardMsg))
870
871 def assertNotIsInstance(self, obj, cls, msg=None):
872 """Included for symmetry with assertIsInstance."""
873 if isinstance(obj, cls):
Michael Foord225a0992010-02-18 20:30:09 +0000874 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
Georg Brandlf895cf52009-10-01 20:59:31 +0000875 self.fail(self._formatMessage(msg, standardMsg))
876
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000877 def assertRaisesRegexp(self, expected_exception, expected_regexp,
878 callable_obj=None, *args, **kwargs):
879 """Asserts that the message in a raised exception matches a regexp.
880
881 Args:
882 expected_exception: Exception class expected to be raised.
883 expected_regexp: Regexp (re pattern object or string) expected
884 to be found in error message.
885 callable_obj: Function to be called.
886 args: Extra args.
887 kwargs: Extra kwargs.
888 """
889 context = _AssertRaisesContext(expected_exception, self, expected_regexp)
890 if callable_obj is None:
891 return context
892 with context:
893 callable_obj(*args, **kwargs)
894
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000895 def assertRegexpMatches(self, text, expected_regexp, msg=None):
896 if isinstance(expected_regexp, basestring):
897 expected_regexp = re.compile(expected_regexp)
898 if not expected_regexp.search(text):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000899 msg = msg or "Regexp didn't match"
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000900 msg = '%s: %r not found in %r' % (msg, expected_regexp.pattern, text)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000901 raise self.failureException(msg)
902
903
904class FunctionTestCase(TestCase):
905 """A test case that wraps a test function.
906
907 This is useful for slipping pre-existing test functions into the
908 unittest framework. Optionally, set-up and tidy-up functions can be
909 supplied. As with TestCase, the tidy-up ('tearDown') function will
910 always be called if the set-up ('setUp') function ran successfully.
911 """
912
913 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
914 super(FunctionTestCase, self).__init__()
915 self._setUpFunc = setUp
916 self._tearDownFunc = tearDown
917 self._testFunc = testFunc
918 self._description = description
919
920 def setUp(self):
921 if self._setUpFunc is not None:
922 self._setUpFunc()
923
924 def tearDown(self):
925 if self._tearDownFunc is not None:
926 self._tearDownFunc()
927
928 def runTest(self):
929 self._testFunc()
930
931 def id(self):
932 return self._testFunc.__name__
933
934 def __eq__(self, other):
935 if not isinstance(other, self.__class__):
936 return NotImplemented
937
938 return self._setUpFunc == other._setUpFunc and \
939 self._tearDownFunc == other._tearDownFunc and \
940 self._testFunc == other._testFunc and \
941 self._description == other._description
942
943 def __ne__(self, other):
944 return not self == other
945
946 def __hash__(self):
947 return hash((type(self), self._setUpFunc, self._tearDownFunc,
948 self._testFunc, self._description))
949
950 def __str__(self):
Michael Foord225a0992010-02-18 20:30:09 +0000951 return "%s (%s)" % (strclass(self.__class__),
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000952 self._testFunc.__name__)
953
954 def __repr__(self):
Michael Foord225a0992010-02-18 20:30:09 +0000955 return "<%s tec=%s>" % (strclass(self.__class__),
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000956 self._testFunc)
957
958 def shortDescription(self):
959 if self._description is not None:
960 return self._description
961 doc = self._testFunc.__doc__
962 return doc and doc.split("\n")[0].strip() or None