blob: 3940daa4c4e7cf37a77c27f91da07d9f1c83091c [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
Michael Foord98e7b762010-03-20 03:00:34 +000011from .util import (
12 strclass, safe_repr, sorted_list_difference, unorderable_list_difference
13)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +000014
Michael Foordb1aa30f2010-03-22 00:06:30 +000015__unittest = True
Michael Foordb1aa30f2010-03-22 00:06:30 +000016
Michael Foord5fe21ff2010-06-05 13:38:16 +000017
18DIFF_OMITTED = ('\nDiff is %s characters long. '
19 'Set self.maxDiff to None to see it.')
20
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +000021class SkipTest(Exception):
22 """
23 Raise this exception in a test to skip it.
24
25 Usually you can use TestResult.skip() or one of the skipping decorators
26 instead of raising this directly.
27 """
28 pass
29
30class _ExpectedFailure(Exception):
31 """
32 Raise this when a test is expected to fail.
33
34 This is an implementation detail.
35 """
36
37 def __init__(self, exc_info):
38 super(_ExpectedFailure, self).__init__()
39 self.exc_info = exc_info
40
41class _UnexpectedSuccess(Exception):
42 """
43 The test was supposed to fail, but it didn't!
44 """
45 pass
46
47def _id(obj):
48 return obj
49
50def skip(reason):
51 """
52 Unconditionally skip a test.
53 """
54 def decorator(test_item):
Michael Foord53e8eea2010-03-07 20:22:12 +000055 if not (isinstance(test_item, type) and issubclass(test_item, TestCase)):
56 @functools.wraps(test_item)
57 def skip_wrapper(*args, **kwargs):
58 raise SkipTest(reason)
59 test_item = skip_wrapper
60
61 test_item.__unittest_skip__ = True
62 test_item.__unittest_skip_why__ = reason
63 return test_item
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +000064 return decorator
65
66def skipIf(condition, reason):
67 """
68 Skip a test if the condition is true.
69 """
70 if condition:
71 return skip(reason)
72 return _id
73
74def skipUnless(condition, reason):
75 """
76 Skip a test unless the condition is true.
77 """
78 if not condition:
79 return skip(reason)
80 return _id
81
82
83def expectedFailure(func):
84 @functools.wraps(func)
85 def wrapper(*args, **kwargs):
86 try:
87 func(*args, **kwargs)
88 except Exception:
89 raise _ExpectedFailure(sys.exc_info())
90 raise _UnexpectedSuccess
91 return wrapper
92
93
94class _AssertRaisesContext(object):
95 """A context manager used to implement TestCase.assertRaises* methods."""
96
97 def __init__(self, expected, test_case, expected_regexp=None):
98 self.expected = expected
99 self.failureException = test_case.failureException
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000100 self.expected_regexp = expected_regexp
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000101
102 def __enter__(self):
Michael Foord2bd52dc2010-02-07 18:44:12 +0000103 return self
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000104
105 def __exit__(self, exc_type, exc_value, tb):
106 if exc_type is None:
107 try:
108 exc_name = self.expected.__name__
109 except AttributeError:
110 exc_name = str(self.expected)
111 raise self.failureException(
112 "{0} not raised".format(exc_name))
113 if not issubclass(exc_type, self.expected):
114 # let unexpected exceptions pass through
115 return False
Georg Brandldc3694b2010-02-07 17:02:22 +0000116 self.exception = exc_value # store for later retrieval
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000117 if self.expected_regexp is None:
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000118 return True
119
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000120 expected_regexp = self.expected_regexp
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000121 if isinstance(expected_regexp, basestring):
122 expected_regexp = re.compile(expected_regexp)
123 if not expected_regexp.search(str(exc_value)):
124 raise self.failureException('"%s" does not match "%s"' %
125 (expected_regexp.pattern, str(exc_value)))
126 return True
127
128
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000129class TestCase(object):
130 """A class whose instances are single test cases.
131
132 By default, the test code itself should be placed in a method named
133 'runTest'.
134
135 If the fixture may be used for many test cases, create as
136 many test methods as are needed. When instantiating such a TestCase
137 subclass, specify in the constructor arguments the name of the test method
138 that the instance is to execute.
139
140 Test authors should subclass TestCase for their own tests. Construction
141 and deconstruction of the test's environment ('fixture') can be
142 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
143
144 If it is necessary to override the __init__ method, the base class
145 __init__ method must always be called. It is important that subclasses
146 should not change the signature of their __init__ method, since instances
147 of the classes are instantiated automatically by parts of the framework
148 in order to be run.
149 """
150
151 # This attribute determines which exception will be raised when
152 # the instance's assertion methods fail; test methods raising this
153 # exception will be deemed to have 'failed' rather than 'errored'
154
155 failureException = AssertionError
156
157 # This attribute determines whether long messages (including repr of
158 # objects used in assert methods) will be printed on failure in *addition*
159 # to any explicit message passed.
160
161 longMessage = False
162
Michael Foordae1bb9a2010-06-09 12:29:56 +0000163 # This attribute sets the maximum length of a diff in failure messages
Michael Foorde37d75f2010-06-05 12:10:52 +0000164 # by assert methods using difflib. It is looked up as an instance attribute
165 # so can be configured by individual tests if required.
Michael Foordc532c572010-06-05 23:58:40 +0000166
Michael Foorde37d75f2010-06-05 12:10:52 +0000167 maxDiff = 80*8
168
Michael Foord5ffa3252010-03-07 22:04:55 +0000169 # Attribute used by TestSuite for classSetUp
170
171 _classSetupFailed = False
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000172
173 def __init__(self, methodName='runTest'):
174 """Create an instance of the class that will use the named test
175 method when executed. Raises a ValueError if the instance does
176 not have a method with the specified name.
177 """
178 self._testMethodName = methodName
179 self._resultForDoCleanups = None
180 try:
181 testMethod = getattr(self, methodName)
182 except AttributeError:
Michael Foordc2294dd2010-02-18 21:37:07 +0000183 raise ValueError("no such test method in %s: %s" %
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000184 (self.__class__, methodName))
185 self._testMethodDoc = testMethod.__doc__
186 self._cleanups = []
187
188 # Map types to custom assertEqual functions that will compare
189 # instances of said type in more detail to generate a more useful
190 # error message.
191 self._type_equality_funcs = {}
192 self.addTypeEqualityFunc(dict, self.assertDictEqual)
193 self.addTypeEqualityFunc(list, self.assertListEqual)
194 self.addTypeEqualityFunc(tuple, self.assertTupleEqual)
195 self.addTypeEqualityFunc(set, self.assertSetEqual)
196 self.addTypeEqualityFunc(frozenset, self.assertSetEqual)
Michael Foordfe6349c2010-02-08 22:41:16 +0000197 self.addTypeEqualityFunc(unicode, self.assertMultiLineEqual)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000198
199 def addTypeEqualityFunc(self, typeobj, function):
200 """Add a type specific assertEqual style function to compare a type.
201
202 This method is for use by TestCase subclasses that need to register
203 their own type equality functions to provide nicer error messages.
204
205 Args:
206 typeobj: The data type to call this function on when both values
207 are of the same type in assertEqual().
208 function: The callable taking two arguments and an optional
209 msg= argument that raises self.failureException with a
210 useful error message when the two arguments are not equal.
211 """
Benjamin Petersond46430b2009-11-29 22:26:26 +0000212 self._type_equality_funcs[typeobj] = function
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000213
214 def addCleanup(self, function, *args, **kwargs):
215 """Add a function, with arguments, to be called when the test is
216 completed. Functions added are called on a LIFO basis and are
217 called after tearDown on test failure or success.
218
219 Cleanup items are called even if setUp fails (unlike tearDown)."""
220 self._cleanups.append((function, args, kwargs))
221
222 def setUp(self):
223 "Hook method for setting up the test fixture before exercising it."
224 pass
225
226 def tearDown(self):
227 "Hook method for deconstructing the test fixture after testing it."
228 pass
229
Michael Foord5ffa3252010-03-07 22:04:55 +0000230 @classmethod
231 def setUpClass(cls):
232 "Hook method for setting up class fixture before running tests in the class."
233
234 @classmethod
235 def tearDownClass(cls):
236 "Hook method for deconstructing the class fixture after running all tests in the class."
237
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000238 def countTestCases(self):
239 return 1
240
241 def defaultTestResult(self):
242 return result.TestResult()
243
244 def shortDescription(self):
Michael Foorddb43b5a2010-02-10 14:25:12 +0000245 """Returns a one-line description of the test, or None if no
246 description has been provided.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000247
Michael Foorddb43b5a2010-02-10 14:25:12 +0000248 The default implementation of this method returns the first line of
249 the specified test method's docstring.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000250 """
Michael Foorddb43b5a2010-02-10 14:25:12 +0000251 doc = self._testMethodDoc
252 return doc and doc.split("\n")[0].strip() or None
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000253
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000254
255 def id(self):
Michael Foord225a0992010-02-18 20:30:09 +0000256 return "%s.%s" % (strclass(self.__class__), self._testMethodName)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000257
258 def __eq__(self, other):
259 if type(self) is not type(other):
260 return NotImplemented
261
262 return self._testMethodName == other._testMethodName
263
264 def __ne__(self, other):
265 return not self == other
266
267 def __hash__(self):
268 return hash((type(self), self._testMethodName))
269
270 def __str__(self):
Michael Foord225a0992010-02-18 20:30:09 +0000271 return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000272
273 def __repr__(self):
274 return "<%s testMethod=%s>" % \
Michael Foord225a0992010-02-18 20:30:09 +0000275 (strclass(self.__class__), self._testMethodName)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000276
Michael Foordae3db0a2010-02-22 23:28:32 +0000277 def _addSkip(self, result, reason):
278 addSkip = getattr(result, 'addSkip', None)
279 if addSkip is not None:
280 addSkip(self, reason)
281 else:
282 warnings.warn("TestResult has no addSkip method, skips not reported",
283 RuntimeWarning, 2)
284 result.addSuccess(self)
285
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000286 def run(self, result=None):
287 orig_result = result
288 if result is None:
289 result = self.defaultTestResult()
290 startTestRun = getattr(result, 'startTestRun', None)
291 if startTestRun is not None:
292 startTestRun()
293
294 self._resultForDoCleanups = result
295 result.startTest(self)
Michael Foord53e8eea2010-03-07 20:22:12 +0000296
297 testMethod = getattr(self, self._testMethodName)
298 if (getattr(self.__class__, "__unittest_skip__", False) or
299 getattr(testMethod, "__unittest_skip__", False)):
300 # If the class or method was skipped.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000301 try:
Michael Foord53e8eea2010-03-07 20:22:12 +0000302 skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
303 or getattr(testMethod, '__unittest_skip_why__', ''))
304 self._addSkip(result, skip_why)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000305 finally:
306 result.stopTest(self)
307 return
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000308 try:
309 success = False
310 try:
311 self.setUp()
312 except SkipTest as e:
Michael Foordae3db0a2010-02-22 23:28:32 +0000313 self._addSkip(result, str(e))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000314 except Exception:
315 result.addError(self, sys.exc_info())
316 else:
317 try:
318 testMethod()
319 except self.failureException:
320 result.addFailure(self, sys.exc_info())
321 except _ExpectedFailure as e:
Michael Foordae3db0a2010-02-22 23:28:32 +0000322 addExpectedFailure = getattr(result, 'addExpectedFailure', None)
323 if addExpectedFailure is not None:
324 addExpectedFailure(self, e.exc_info)
325 else:
326 warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
327 RuntimeWarning)
328 result.addSuccess(self)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000329 except _UnexpectedSuccess:
Michael Foordae3db0a2010-02-22 23:28:32 +0000330 addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
331 if addUnexpectedSuccess is not None:
332 addUnexpectedSuccess(self)
333 else:
334 warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures",
335 RuntimeWarning)
336 result.addFailure(self, sys.exc_info())
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000337 except SkipTest as e:
Michael Foordae3db0a2010-02-22 23:28:32 +0000338 self._addSkip(result, str(e))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000339 except Exception:
340 result.addError(self, sys.exc_info())
341 else:
342 success = True
343
344 try:
345 self.tearDown()
346 except Exception:
347 result.addError(self, sys.exc_info())
348 success = False
349
350 cleanUpSuccess = self.doCleanups()
351 success = success and cleanUpSuccess
352 if success:
353 result.addSuccess(self)
354 finally:
355 result.stopTest(self)
356 if orig_result is None:
357 stopTestRun = getattr(result, 'stopTestRun', None)
358 if stopTestRun is not None:
359 stopTestRun()
360
361 def doCleanups(self):
362 """Execute all cleanup functions. Normally called for you after
363 tearDown."""
364 result = self._resultForDoCleanups
365 ok = True
366 while self._cleanups:
367 function, args, kwargs = self._cleanups.pop(-1)
368 try:
369 function(*args, **kwargs)
370 except Exception:
371 ok = False
372 result.addError(self, sys.exc_info())
373 return ok
374
375 def __call__(self, *args, **kwds):
376 return self.run(*args, **kwds)
377
378 def debug(self):
379 """Run the test without collecting errors in a TestResult"""
380 self.setUp()
381 getattr(self, self._testMethodName)()
382 self.tearDown()
Michael Foord0fedb282010-06-08 22:44:52 +0000383 while self._cleanups:
384 function, args, kwargs = self._cleanups.pop(-1)
385 function(*args, **kwargs)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000386
387 def skipTest(self, reason):
388 """Skip this test."""
389 raise SkipTest(reason)
390
391 def fail(self, msg=None):
392 """Fail immediately, with the given message."""
393 raise self.failureException(msg)
394
395 def assertFalse(self, expr, msg=None):
Ezio Melottic139a562010-12-18 17:58:29 +0000396 """Check that the expression is false."""
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000397 if expr:
Ezio Melottic139a562010-12-18 17:58:29 +0000398 msg = self._formatMessage(msg, "%s is not false" % safe_repr(expr))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000399 raise self.failureException(msg)
400
401 def assertTrue(self, expr, msg=None):
Ezio Melottic139a562010-12-18 17:58:29 +0000402 """Check that the expression is true."""
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000403 if not expr:
Ezio Melottic139a562010-12-18 17:58:29 +0000404 msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000405 raise self.failureException(msg)
406
407 def _formatMessage(self, msg, standardMsg):
408 """Honour the longMessage attribute when generating failure messages.
409 If longMessage is False this means:
410 * Use only an explicit message if it is provided
411 * Otherwise use the standard message for the assert
412
413 If longMessage is True:
414 * Use the standard message
415 * If an explicit message is provided, plus ' : ' and the explicit message
416 """
417 if not self.longMessage:
418 return msg or standardMsg
419 if msg is None:
420 return standardMsg
Michael Foord53e8eea2010-03-07 20:22:12 +0000421 try:
422 # don't switch to '{}' formatting in Python 2.X
423 # it changes the way unicode input is handled
424 return '%s : %s' % (standardMsg, msg)
425 except UnicodeDecodeError:
426 return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000427
428
429 def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
430 """Fail unless an exception of class excClass is thrown
431 by callableObj when invoked with arguments args and keyword
432 arguments kwargs. If a different type of exception is
433 thrown, it will not be caught, and the test case will be
434 deemed to have suffered an error, exactly as for an
435 unexpected exception.
436
437 If called with callableObj omitted or None, will return a
438 context object used like this::
439
Michael Foordd0edec32010-02-05 22:55:09 +0000440 with self.assertRaises(SomeException):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000441 do_something()
Michael Foordd0edec32010-02-05 22:55:09 +0000442
443 The context manager keeps a reference to the exception as
Ezio Melotticd4f6572010-02-08 21:52:08 +0000444 the 'exception' attribute. This allows you to inspect the
Michael Foordd0edec32010-02-05 22:55:09 +0000445 exception after the assertion::
446
447 with self.assertRaises(SomeException) as cm:
448 do_something()
Georg Brandldc3694b2010-02-07 17:02:22 +0000449 the_exception = cm.exception
Michael Foord757cc4d2010-02-05 23:22:37 +0000450 self.assertEqual(the_exception.error_code, 3)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000451 """
452 context = _AssertRaisesContext(excClass, self)
453 if callableObj is None:
454 return context
455 with context:
456 callableObj(*args, **kwargs)
457
458 def _getAssertEqualityFunc(self, first, second):
459 """Get a detailed comparison function for the types of the two args.
460
461 Returns: A callable accepting (first, second, msg=None) that will
462 raise a failure exception if first != second with a useful human
463 readable error message for those types.
464 """
465 #
466 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
467 # and vice versa. I opted for the conservative approach in case
468 # subclasses are not intended to be compared in detail to their super
469 # class instances using a type equality func. This means testing
470 # subtypes won't automagically use the detailed comparison. Callers
471 # should use their type specific assertSpamEqual method to compare
472 # subclasses if the detailed comparison is desired and appropriate.
473 # See the discussion in http://bugs.python.org/issue2578.
474 #
475 if type(first) is type(second):
476 asserter = self._type_equality_funcs.get(type(first))
477 if asserter is not None:
Benjamin Petersond46430b2009-11-29 22:26:26 +0000478 return asserter
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000479
480 return self._baseAssertEqual
481
482 def _baseAssertEqual(self, first, second, msg=None):
483 """The default assertEqual implementation, not type specific."""
484 if not first == second:
Michael Foord225a0992010-02-18 20:30:09 +0000485 standardMsg = '%s != %s' % (safe_repr(first), safe_repr(second))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000486 msg = self._formatMessage(msg, standardMsg)
487 raise self.failureException(msg)
488
489 def assertEqual(self, first, second, msg=None):
490 """Fail if the two objects are unequal as determined by the '=='
491 operator.
492 """
493 assertion_func = self._getAssertEqualityFunc(first, second)
494 assertion_func(first, second, msg=msg)
495
496 def assertNotEqual(self, first, second, msg=None):
497 """Fail if the two objects are equal as determined by the '=='
498 operator.
499 """
500 if not first != second:
Michael Foord225a0992010-02-18 20:30:09 +0000501 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
502 safe_repr(second)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000503 raise self.failureException(msg)
504
Michael Foorda7e08fe2010-03-27 19:10:11 +0000505
506 def assertAlmostEqual(self, first, second, places=None, msg=None, delta=None):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000507 """Fail if the two objects are unequal as determined by their
508 difference rounded to the given number of decimal places
Michael Foorda7e08fe2010-03-27 19:10:11 +0000509 (default 7) and comparing to zero, or by comparing that the
510 between the two objects is more than the given delta.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000511
512 Note that decimal places (from zero) are usually not the same
513 as significant digits (measured from the most signficant digit).
Michael Foordc3f79372009-09-13 16:40:02 +0000514
515 If the two objects compare equal then they will automatically
516 compare almost equal.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000517 """
Michael Foordc3f79372009-09-13 16:40:02 +0000518 if first == second:
Michael Foorda7e08fe2010-03-27 19:10:11 +0000519 # shortcut
Michael Foordc3f79372009-09-13 16:40:02 +0000520 return
Michael Foorda7e08fe2010-03-27 19:10:11 +0000521 if delta is not None and places is not None:
522 raise TypeError("specify delta or places not both")
523
524 if delta is not None:
525 if abs(first - second) <= delta:
526 return
527
528 standardMsg = '%s != %s within %s delta' % (safe_repr(first),
529 safe_repr(second),
530 safe_repr(delta))
531 else:
532 if places is None:
533 places = 7
534
535 if round(abs(second-first), places) == 0:
536 return
537
Michael Foord225a0992010-02-18 20:30:09 +0000538 standardMsg = '%s != %s within %r places' % (safe_repr(first),
539 safe_repr(second),
540 places)
Michael Foorda7e08fe2010-03-27 19:10:11 +0000541 msg = self._formatMessage(msg, standardMsg)
542 raise self.failureException(msg)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000543
Michael Foorda7e08fe2010-03-27 19:10:11 +0000544 def assertNotAlmostEqual(self, first, second, places=None, msg=None, delta=None):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000545 """Fail if the two objects are equal as determined by their
546 difference rounded to the given number of decimal places
Michael Foorda7e08fe2010-03-27 19:10:11 +0000547 (default 7) and comparing to zero, or by comparing that the
548 between the two objects is less than the given delta.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000549
550 Note that decimal places (from zero) are usually not the same
551 as significant digits (measured from the most signficant digit).
Michael Foordc3f79372009-09-13 16:40:02 +0000552
553 Objects that are equal automatically fail.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000554 """
Michael Foorda7e08fe2010-03-27 19:10:11 +0000555 if delta is not None and places is not None:
556 raise TypeError("specify delta or places not both")
557 if delta is not None:
558 if not (first == second) and abs(first - second) > delta:
559 return
560 standardMsg = '%s == %s within %s delta' % (safe_repr(first),
561 safe_repr(second),
562 safe_repr(delta))
563 else:
564 if places is None:
565 places = 7
566 if not (first == second) and round(abs(second-first), places) != 0:
567 return
Michael Foord225a0992010-02-18 20:30:09 +0000568 standardMsg = '%s == %s within %r places' % (safe_repr(first),
Michael Foorda7e08fe2010-03-27 19:10:11 +0000569 safe_repr(second),
570 places)
571
572 msg = self._formatMessage(msg, standardMsg)
573 raise self.failureException(msg)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000574
575 # Synonyms for assertion methods
576
577 # The plurals are undocumented. Keep them that way to discourage use.
578 # Do not add more. Do not remove.
579 # Going through a deprecation cycle on these would annoy many people.
580 assertEquals = assertEqual
581 assertNotEquals = assertNotEqual
582 assertAlmostEquals = assertAlmostEqual
583 assertNotAlmostEquals = assertNotAlmostEqual
Michael Foord67dfc772010-02-10 14:31:30 +0000584 assert_ = assertTrue
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000585
586 # These fail* assertion method names are pending deprecation and will
587 # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
588 def _deprecate(original_func):
589 def deprecated_func(*args, **kwargs):
590 warnings.warn(
591 'Please use {0} instead.'.format(original_func.__name__),
592 PendingDeprecationWarning, 2)
593 return original_func(*args, **kwargs)
594 return deprecated_func
595
596 failUnlessEqual = _deprecate(assertEqual)
597 failIfEqual = _deprecate(assertNotEqual)
598 failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
599 failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
600 failUnless = _deprecate(assertTrue)
601 failUnlessRaises = _deprecate(assertRaises)
602 failIf = _deprecate(assertFalse)
603
Michael Foorde37d75f2010-06-05 12:10:52 +0000604 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000605 """An equality assertion for ordered sequences (like lists and tuples).
606
R. David Murray05b41712010-01-29 19:35:39 +0000607 For the purposes of this function, a valid ordered sequence type is one
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000608 which can be indexed, has a length, and has an equality operator.
609
610 Args:
611 seq1: The first sequence to compare.
612 seq2: The second sequence to compare.
613 seq_type: The expected datatype of the sequences, or None if no
614 datatype should be enforced.
615 msg: Optional message to use on failure instead of a list of
616 differences.
617 """
Florent Xicluna4a0f8b82010-03-21 10:50:44 +0000618 if seq_type is not None:
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000619 seq_type_name = seq_type.__name__
620 if not isinstance(seq1, seq_type):
Michael Foord225a0992010-02-18 20:30:09 +0000621 raise self.failureException('First sequence is not a %s: %s'
622 % (seq_type_name, safe_repr(seq1)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000623 if not isinstance(seq2, seq_type):
Michael Foord225a0992010-02-18 20:30:09 +0000624 raise self.failureException('Second sequence is not a %s: %s'
625 % (seq_type_name, safe_repr(seq2)))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000626 else:
627 seq_type_name = "sequence"
628
629 differing = None
630 try:
631 len1 = len(seq1)
632 except (TypeError, NotImplementedError):
633 differing = 'First %s has no length. Non-sequence?' % (
634 seq_type_name)
635
636 if differing is None:
637 try:
638 len2 = len(seq2)
639 except (TypeError, NotImplementedError):
640 differing = 'Second %s has no length. Non-sequence?' % (
641 seq_type_name)
642
643 if differing is None:
644 if seq1 == seq2:
645 return
646
Michael Foord225a0992010-02-18 20:30:09 +0000647 seq1_repr = safe_repr(seq1)
648 seq2_repr = safe_repr(seq2)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000649 if len(seq1_repr) > 30:
650 seq1_repr = seq1_repr[:30] + '...'
651 if len(seq2_repr) > 30:
652 seq2_repr = seq2_repr[:30] + '...'
653 elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
654 differing = '%ss differ: %s != %s\n' % elements
655
656 for i in xrange(min(len1, len2)):
657 try:
658 item1 = seq1[i]
659 except (TypeError, IndexError, NotImplementedError):
660 differing += ('\nUnable to index element %d of first %s\n' %
661 (i, seq_type_name))
662 break
663
664 try:
665 item2 = seq2[i]
666 except (TypeError, IndexError, NotImplementedError):
667 differing += ('\nUnable to index element %d of second %s\n' %
668 (i, seq_type_name))
669 break
670
671 if item1 != item2:
672 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
673 (i, item1, item2))
674 break
675 else:
676 if (len1 == len2 and seq_type is None and
677 type(seq1) != type(seq2)):
678 # The sequences are the same, but have differing types.
679 return
680
681 if len1 > len2:
682 differing += ('\nFirst %s contains %d additional '
683 'elements.\n' % (seq_type_name, len1 - len2))
684 try:
685 differing += ('First extra element %d:\n%s\n' %
686 (len2, seq1[len2]))
687 except (TypeError, IndexError, NotImplementedError):
688 differing += ('Unable to index element %d '
689 'of first %s\n' % (len2, seq_type_name))
690 elif len1 < len2:
691 differing += ('\nSecond %s contains %d additional '
692 'elements.\n' % (seq_type_name, len2 - len1))
693 try:
694 differing += ('First extra element %d:\n%s\n' %
695 (len1, seq2[len1]))
696 except (TypeError, IndexError, NotImplementedError):
697 differing += ('Unable to index element %d '
698 'of second %s\n' % (len1, seq_type_name))
Michael Foord01007022010-06-05 11:23:51 +0000699 standardMsg = differing
700 diffMsg = '\n' + '\n'.join(
Georg Brandl46cc46a2009-10-01 20:11:14 +0000701 difflib.ndiff(pprint.pformat(seq1).splitlines(),
702 pprint.pformat(seq2).splitlines()))
Michael Foorde37d75f2010-06-05 12:10:52 +0000703 standardMsg = self._truncateMessage(standardMsg, diffMsg)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000704 msg = self._formatMessage(msg, standardMsg)
705 self.fail(msg)
706
Michael Foorde37d75f2010-06-05 12:10:52 +0000707 def _truncateMessage(self, message, diff):
708 max_diff = self.maxDiff
Michael Foorda4412872010-06-05 11:46:59 +0000709 if max_diff is None or len(diff) <= max_diff:
710 return message + diff
Michael Foord5fe21ff2010-06-05 13:38:16 +0000711 return message + (DIFF_OMITTED % len(diff))
Michael Foorda4412872010-06-05 11:46:59 +0000712
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000713 def assertListEqual(self, list1, list2, msg=None):
714 """A list-specific equality assertion.
715
716 Args:
717 list1: The first list to compare.
718 list2: The second list to compare.
719 msg: Optional message to use on failure instead of a list of
720 differences.
721
722 """
723 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
724
725 def assertTupleEqual(self, tuple1, tuple2, msg=None):
726 """A tuple-specific equality assertion.
727
728 Args:
729 tuple1: The first tuple to compare.
730 tuple2: The second tuple to compare.
731 msg: Optional message to use on failure instead of a list of
732 differences.
733 """
734 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
735
736 def assertSetEqual(self, set1, set2, msg=None):
737 """A set-specific equality assertion.
738
739 Args:
740 set1: The first set to compare.
741 set2: The second set to compare.
742 msg: Optional message to use on failure instead of a list of
743 differences.
744
Michael Foord98e7b762010-03-20 03:00:34 +0000745 assertSetEqual uses ducktyping to support different types of sets, and
746 is optimized for sets specifically (parameters must support a
747 difference method).
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000748 """
749 try:
750 difference1 = set1.difference(set2)
751 except TypeError, e:
752 self.fail('invalid type when attempting set difference: %s' % e)
753 except AttributeError, e:
754 self.fail('first argument does not support set difference: %s' % e)
755
756 try:
757 difference2 = set2.difference(set1)
758 except TypeError, e:
759 self.fail('invalid type when attempting set difference: %s' % e)
760 except AttributeError, e:
761 self.fail('second argument does not support set difference: %s' % e)
762
763 if not (difference1 or difference2):
764 return
765
766 lines = []
767 if difference1:
768 lines.append('Items in the first set but not the second:')
769 for item in difference1:
770 lines.append(repr(item))
771 if difference2:
772 lines.append('Items in the second set but not the first:')
773 for item in difference2:
774 lines.append(repr(item))
775
776 standardMsg = '\n'.join(lines)
777 self.fail(self._formatMessage(msg, standardMsg))
778
779 def assertIn(self, member, container, msg=None):
780 """Just like self.assertTrue(a in b), but with a nicer default message."""
781 if member not in container:
Michael Foord225a0992010-02-18 20:30:09 +0000782 standardMsg = '%s not found in %s' % (safe_repr(member),
783 safe_repr(container))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000784 self.fail(self._formatMessage(msg, standardMsg))
785
786 def assertNotIn(self, member, container, msg=None):
787 """Just like self.assertTrue(a not in b), but with a nicer default message."""
788 if member in container:
Michael Foord225a0992010-02-18 20:30:09 +0000789 standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
790 safe_repr(container))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000791 self.fail(self._formatMessage(msg, standardMsg))
792
793 def assertIs(self, expr1, expr2, msg=None):
794 """Just like self.assertTrue(a is b), but with a nicer default message."""
795 if expr1 is not expr2:
Michael Foord225a0992010-02-18 20:30:09 +0000796 standardMsg = '%s is not %s' % (safe_repr(expr1),
Michael Foordc2294dd2010-02-18 21:37:07 +0000797 safe_repr(expr2))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000798 self.fail(self._formatMessage(msg, standardMsg))
799
800 def assertIsNot(self, expr1, expr2, msg=None):
801 """Just like self.assertTrue(a is not b), but with a nicer default message."""
802 if expr1 is expr2:
Michael Foord225a0992010-02-18 20:30:09 +0000803 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000804 self.fail(self._formatMessage(msg, standardMsg))
805
806 def assertDictEqual(self, d1, d2, msg=None):
Ezio Melotti2623a372010-11-21 13:34:58 +0000807 self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
808 self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000809
810 if d1 != d2:
Michael Foord674648e2010-06-05 12:58:39 +0000811 standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True))
Michael Foorde37d75f2010-06-05 12:10:52 +0000812 diff = ('\n' + '\n'.join(difflib.ndiff(
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000813 pprint.pformat(d1).splitlines(),
814 pprint.pformat(d2).splitlines())))
Michael Foord674648e2010-06-05 12:58:39 +0000815 standardMsg = self._truncateMessage(standardMsg, diff)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000816 self.fail(self._formatMessage(msg, standardMsg))
817
818 def assertDictContainsSubset(self, expected, actual, msg=None):
819 """Checks whether actual is a superset of expected."""
820 missing = []
821 mismatched = []
822 for key, value in expected.iteritems():
823 if key not in actual:
824 missing.append(key)
825 elif value != actual[key]:
Georg Brandl46cc46a2009-10-01 20:11:14 +0000826 mismatched.append('%s, expected: %s, actual: %s' %
Michael Foordc2294dd2010-02-18 21:37:07 +0000827 (safe_repr(key), safe_repr(value),
828 safe_repr(actual[key])))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000829
830 if not (missing or mismatched):
831 return
832
833 standardMsg = ''
834 if missing:
Michael Foord225a0992010-02-18 20:30:09 +0000835 standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
836 missing)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000837 if mismatched:
838 if standardMsg:
839 standardMsg += '; '
840 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
841
842 self.fail(self._formatMessage(msg, standardMsg))
843
Michael Foord98e7b762010-03-20 03:00:34 +0000844 def assertItemsEqual(self, expected_seq, actual_seq, msg=None):
845 """An unordered sequence / set specific comparison. It asserts that
846 expected_seq and actual_seq contain the same elements. It is
847 the equivalent of::
848
849 self.assertEqual(sorted(expected_seq), sorted(actual_seq))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000850
851 Raises with an error message listing which elements of expected_seq
852 are missing from actual_seq and vice versa if any.
Michael Foordd0edec32010-02-05 22:55:09 +0000853
Michael Foord98e7b762010-03-20 03:00:34 +0000854 Asserts that each element has the same count in both sequences.
855 Example:
856 - [0, 1, 1] and [1, 0, 1] compare equal.
857 - [0, 0, 1] and [0, 1] compare unequal.
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000858 """
Florent Xicluna1f3b4e12010-03-07 12:14:25 +0000859 with warnings.catch_warnings():
860 if sys.py3kwarning:
861 # Silence Py3k warning raised during the sorting
Florent Xicluna4a0f8b82010-03-21 10:50:44 +0000862 for _msg in ["(code|dict|type) inequality comparisons",
Michael Foord98e7b762010-03-20 03:00:34 +0000863 "builtin_function_or_method order comparisons",
864 "comparing unequal types"]:
Michael Foorda7152552010-03-07 23:10:36 +0000865 warnings.filterwarnings("ignore", _msg, DeprecationWarning)
Florent Xicluna1f3b4e12010-03-07 12:14:25 +0000866 try:
Florent Xicluna1f3b4e12010-03-07 12:14:25 +0000867 expected = sorted(expected_seq)
868 actual = sorted(actual_seq)
Michael Foord98e7b762010-03-20 03:00:34 +0000869 except TypeError:
870 # Unsortable items (example: set(), complex(), ...)
871 expected = list(expected_seq)
872 actual = list(actual_seq)
873 missing, unexpected = unorderable_list_difference(
874 expected, actual, ignore_duplicate=False
875 )
876 else:
877 return self.assertSequenceEqual(expected, actual, msg=msg)
878
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000879 errors = []
880 if missing:
Michael Foord225a0992010-02-18 20:30:09 +0000881 errors.append('Expected, but missing:\n %s' %
Michael Foord98e7b762010-03-20 03:00:34 +0000882 safe_repr(missing))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000883 if unexpected:
Michael Foord225a0992010-02-18 20:30:09 +0000884 errors.append('Unexpected, but present:\n %s' %
Michael Foord98e7b762010-03-20 03:00:34 +0000885 safe_repr(unexpected))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000886 if errors:
887 standardMsg = '\n'.join(errors)
888 self.fail(self._formatMessage(msg, standardMsg))
889
890 def assertMultiLineEqual(self, first, second, msg=None):
891 """Assert that two multi-line strings are equal."""
Ezio Melotti2623a372010-11-21 13:34:58 +0000892 self.assertIsInstance(first, basestring,
893 'First argument is not a string')
894 self.assertIsInstance(second, basestring,
895 'Second argument is not a string')
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000896
897 if first != second:
Michael Foord94f071c2010-07-10 13:51:42 +0000898 firstlines = first.splitlines(True)
899 secondlines = second.splitlines(True)
900 if len(firstlines) == 1 and first.strip('\r\n') == first:
901 firstlines = [first + '\n']
902 secondlines = [second + '\n']
903 standardMsg = '%s != %s' % (safe_repr(first, True),
904 safe_repr(second, True))
905 diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines))
Michael Foord674648e2010-06-05 12:58:39 +0000906 standardMsg = self._truncateMessage(standardMsg, diff)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000907 self.fail(self._formatMessage(msg, standardMsg))
908
909 def assertLess(self, a, b, msg=None):
910 """Just like self.assertTrue(a < b), but with a nicer default message."""
911 if not a < b:
Michael Foord225a0992010-02-18 20:30:09 +0000912 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000913 self.fail(self._formatMessage(msg, standardMsg))
914
915 def assertLessEqual(self, a, b, msg=None):
916 """Just like self.assertTrue(a <= b), but with a nicer default message."""
917 if not a <= b:
Michael Foord225a0992010-02-18 20:30:09 +0000918 standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000919 self.fail(self._formatMessage(msg, standardMsg))
920
921 def assertGreater(self, a, b, msg=None):
922 """Just like self.assertTrue(a > b), but with a nicer default message."""
923 if not a > b:
Michael Foord225a0992010-02-18 20:30:09 +0000924 standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000925 self.fail(self._formatMessage(msg, standardMsg))
926
927 def assertGreaterEqual(self, a, b, msg=None):
928 """Just like self.assertTrue(a >= b), but with a nicer default message."""
929 if not a >= b:
Michael Foord225a0992010-02-18 20:30:09 +0000930 standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000931 self.fail(self._formatMessage(msg, standardMsg))
932
933 def assertIsNone(self, obj, msg=None):
934 """Same as self.assertTrue(obj is None), with a nicer default message."""
935 if obj is not None:
Michael Foord225a0992010-02-18 20:30:09 +0000936 standardMsg = '%s is not None' % (safe_repr(obj),)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000937 self.fail(self._formatMessage(msg, standardMsg))
938
939 def assertIsNotNone(self, obj, msg=None):
940 """Included for symmetry with assertIsNone."""
941 if obj is None:
942 standardMsg = 'unexpectedly None'
943 self.fail(self._formatMessage(msg, standardMsg))
944
Georg Brandlf895cf52009-10-01 20:59:31 +0000945 def assertIsInstance(self, obj, cls, msg=None):
946 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
947 default message."""
948 if not isinstance(obj, cls):
Michael Foord225a0992010-02-18 20:30:09 +0000949 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
Georg Brandlf895cf52009-10-01 20:59:31 +0000950 self.fail(self._formatMessage(msg, standardMsg))
951
952 def assertNotIsInstance(self, obj, cls, msg=None):
953 """Included for symmetry with assertIsInstance."""
954 if isinstance(obj, cls):
Michael Foord225a0992010-02-18 20:30:09 +0000955 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
Georg Brandlf895cf52009-10-01 20:59:31 +0000956 self.fail(self._formatMessage(msg, standardMsg))
957
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000958 def assertRaisesRegexp(self, expected_exception, expected_regexp,
959 callable_obj=None, *args, **kwargs):
960 """Asserts that the message in a raised exception matches a regexp.
961
962 Args:
963 expected_exception: Exception class expected to be raised.
964 expected_regexp: Regexp (re pattern object or string) expected
965 to be found in error message.
966 callable_obj: Function to be called.
967 args: Extra args.
968 kwargs: Extra kwargs.
969 """
970 context = _AssertRaisesContext(expected_exception, self, expected_regexp)
971 if callable_obj is None:
972 return context
973 with context:
974 callable_obj(*args, **kwargs)
975
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000976 def assertRegexpMatches(self, text, expected_regexp, msg=None):
Michael Foord959c16d2010-05-08 16:40:52 +0000977 """Fail the test unless the text matches the regular expression."""
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000978 if isinstance(expected_regexp, basestring):
979 expected_regexp = re.compile(expected_regexp)
980 if not expected_regexp.search(text):
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000981 msg = msg or "Regexp didn't match"
Georg Brandlb0eb4d32010-02-07 11:34:15 +0000982 msg = '%s: %r not found in %r' % (msg, expected_regexp.pattern, text)
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000983 raise self.failureException(msg)
984
Michael Foorda04c7a02010-04-02 22:55:59 +0000985 def assertNotRegexpMatches(self, text, unexpected_regexp, msg=None):
Michael Foord959c16d2010-05-08 16:40:52 +0000986 """Fail the test if the text matches the regular expression."""
Michael Foorda04c7a02010-04-02 22:55:59 +0000987 if isinstance(unexpected_regexp, basestring):
988 unexpected_regexp = re.compile(unexpected_regexp)
989 match = unexpected_regexp.search(text)
990 if match:
991 msg = msg or "Regexp matched"
992 msg = '%s: %r matches %r in %r' % (msg,
993 text[match.start():match.end()],
994 unexpected_regexp.pattern,
995 text)
996 raise self.failureException(msg)
997
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +0000998
999class FunctionTestCase(TestCase):
1000 """A test case that wraps a test function.
1001
1002 This is useful for slipping pre-existing test functions into the
1003 unittest framework. Optionally, set-up and tidy-up functions can be
1004 supplied. As with TestCase, the tidy-up ('tearDown') function will
1005 always be called if the set-up ('setUp') function ran successfully.
1006 """
1007
1008 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
1009 super(FunctionTestCase, self).__init__()
1010 self._setUpFunc = setUp
1011 self._tearDownFunc = tearDown
1012 self._testFunc = testFunc
1013 self._description = description
1014
1015 def setUp(self):
1016 if self._setUpFunc is not None:
1017 self._setUpFunc()
1018
1019 def tearDown(self):
1020 if self._tearDownFunc is not None:
1021 self._tearDownFunc()
1022
1023 def runTest(self):
1024 self._testFunc()
1025
1026 def id(self):
1027 return self._testFunc.__name__
1028
1029 def __eq__(self, other):
1030 if not isinstance(other, self.__class__):
1031 return NotImplemented
1032
1033 return self._setUpFunc == other._setUpFunc and \
1034 self._tearDownFunc == other._tearDownFunc and \
1035 self._testFunc == other._testFunc and \
1036 self._description == other._description
1037
1038 def __ne__(self, other):
1039 return not self == other
1040
1041 def __hash__(self):
1042 return hash((type(self), self._setUpFunc, self._tearDownFunc,
1043 self._testFunc, self._description))
1044
1045 def __str__(self):
Michael Foord225a0992010-02-18 20:30:09 +00001046 return "%s (%s)" % (strclass(self.__class__),
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +00001047 self._testFunc.__name__)
1048
1049 def __repr__(self):
Michael Foord225a0992010-02-18 20:30:09 +00001050 return "<%s tec=%s>" % (strclass(self.__class__),
Benjamin Petersond7b0eeb2009-07-19 20:18:21 +00001051 self._testFunc)
1052
1053 def shortDescription(self):
1054 if self._description is not None:
1055 return self._description
1056 doc = self._testFunc.__doc__
1057 return doc and doc.split("\n")[0].strip() or None