blob: 03346a158c2fd8661daf64fda2d56995b5f5131e [file] [log] [blame]
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001"""Test case implementation"""
2
3import sys
4import functools
5import difflib
6import pprint
7import re
8import warnings
9
Benjamin Peterson847a4112010-03-14 15:04:17 +000010from . import result
11from .util import (strclass, safe_repr, sorted_list_difference,
12 unorderable_list_difference)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000013
Benjamin Petersondccc1fc2010-03-22 00:15:53 +000014__unittest = True
Benjamin Petersonbed7d042009-07-19 21:01:52 +000015
Michael Foord9dad32e2010-06-05 13:49:56 +000016
17DIFF_OMITTED = ('\nDiff is %s characters long. '
18 'Set self.maxDiff to None to see it.')
19
Benjamin Petersonbed7d042009-07-19 21:01:52 +000020class SkipTest(Exception):
21 """
22 Raise this exception in a test to skip it.
23
24 Usually you can use TestResult.skip() or one of the skipping decorators
25 instead of raising this directly.
26 """
27 pass
28
29class _ExpectedFailure(Exception):
30 """
31 Raise this when a test is expected to fail.
32
33 This is an implementation detail.
34 """
35
36 def __init__(self, exc_info):
37 super(_ExpectedFailure, self).__init__()
38 self.exc_info = exc_info
39
40class _UnexpectedSuccess(Exception):
41 """
42 The test was supposed to fail, but it didn't!
43 """
44 pass
45
46def _id(obj):
47 return obj
48
49def skip(reason):
50 """
51 Unconditionally skip a test.
52 """
53 def decorator(test_item):
Benjamin Peterson847a4112010-03-14 15:04:17 +000054 if not (isinstance(test_item, type) and issubclass(test_item, TestCase)):
55 @functools.wraps(test_item)
56 def skip_wrapper(*args, **kwargs):
57 raise SkipTest(reason)
58 test_item = skip_wrapper
59
60 test_item.__unittest_skip__ = True
61 test_item.__unittest_skip_why__ = reason
62 return test_item
Benjamin Petersonbed7d042009-07-19 21:01:52 +000063 return decorator
64
65def skipIf(condition, reason):
66 """
67 Skip a test if the condition is true.
68 """
69 if condition:
70 return skip(reason)
71 return _id
72
73def skipUnless(condition, reason):
74 """
75 Skip a test unless the condition is true.
76 """
77 if not condition:
78 return skip(reason)
79 return _id
80
81
82def expectedFailure(func):
83 @functools.wraps(func)
84 def wrapper(*args, **kwargs):
85 try:
86 func(*args, **kwargs)
87 except Exception:
88 raise _ExpectedFailure(sys.exc_info())
89 raise _UnexpectedSuccess
90 return wrapper
91
92
93class _AssertRaisesContext(object):
94 """A context manager used to implement TestCase.assertRaises* methods."""
95
96 def __init__(self, expected, test_case, callable_obj=None,
97 expected_regexp=None):
98 self.expected = expected
99 self.failureException = test_case.failureException
100 if callable_obj is not None:
101 try:
102 self.obj_name = callable_obj.__name__
103 except AttributeError:
104 self.obj_name = str(callable_obj)
105 else:
106 self.obj_name = None
Georg Brandl89fad142010-03-14 10:23:39 +0000107 self.expected_regexp = expected_regexp
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000108
109 def __enter__(self):
Ezio Melotti49008232010-02-08 21:57:48 +0000110 return self
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000111
112 def __exit__(self, exc_type, exc_value, tb):
113 if exc_type is None:
114 try:
115 exc_name = self.expected.__name__
116 except AttributeError:
117 exc_name = str(self.expected)
118 if self.obj_name:
119 raise self.failureException("{0} not raised by {1}"
120 .format(exc_name, self.obj_name))
121 else:
122 raise self.failureException("{0} not raised"
123 .format(exc_name))
124 if not issubclass(exc_type, self.expected):
125 # let unexpected exceptions pass through
126 return False
Ezio Melotti49008232010-02-08 21:57:48 +0000127 # store exception, without traceback, for later retrieval
128 self.exception = exc_value.with_traceback(None)
Georg Brandl89fad142010-03-14 10:23:39 +0000129 if self.expected_regexp is None:
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000130 return True
131
Georg Brandl89fad142010-03-14 10:23:39 +0000132 expected_regexp = self.expected_regexp
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000133 if isinstance(expected_regexp, (bytes, str)):
134 expected_regexp = re.compile(expected_regexp)
135 if not expected_regexp.search(str(exc_value)):
136 raise self.failureException('"%s" does not match "%s"' %
137 (expected_regexp.pattern, str(exc_value)))
138 return True
139
140
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000141class TestCase(object):
142 """A class whose instances are single test cases.
143
144 By default, the test code itself should be placed in a method named
145 'runTest'.
146
147 If the fixture may be used for many test cases, create as
148 many test methods as are needed. When instantiating such a TestCase
149 subclass, specify in the constructor arguments the name of the test method
150 that the instance is to execute.
151
152 Test authors should subclass TestCase for their own tests. Construction
153 and deconstruction of the test's environment ('fixture') can be
154 implemented by overriding the 'setUp' and 'tearDown' methods respectively.
155
156 If it is necessary to override the __init__ method, the base class
157 __init__ method must always be called. It is important that subclasses
158 should not change the signature of their __init__ method, since instances
159 of the classes are instantiated automatically by parts of the framework
160 in order to be run.
161 """
162
163 # This attribute determines which exception will be raised when
164 # the instance's assertion methods fail; test methods raising this
165 # exception will be deemed to have 'failed' rather than 'errored'
166
167 failureException = AssertionError
168
169 # This attribute determines whether long messages (including repr of
170 # objects used in assert methods) will be printed on failure in *addition*
171 # to any explicit message passed.
172
173 longMessage = False
174
Michael Foordc41d1412010-06-10 16:17:07 +0000175 # This attribute sets the maximum length of a diff in failure messages
Michael Foord085dfd32010-06-05 12:17:02 +0000176 # by assert methods using difflib. It is looked up as an instance attribute
177 # so can be configured by individual tests if required.
Michael Foordd50a6b92010-06-05 23:59:34 +0000178
Michael Foord085dfd32010-06-05 12:17:02 +0000179 maxDiff = 80*8
180
Benjamin Peterson847a4112010-03-14 15:04:17 +0000181 # Attribute used by TestSuite for classSetUp
182
183 _classSetupFailed = False
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000184
185 def __init__(self, methodName='runTest'):
186 """Create an instance of the class that will use the named test
187 method when executed. Raises a ValueError if the instance does
188 not have a method with the specified name.
189 """
190 self._testMethodName = methodName
191 self._resultForDoCleanups = None
192 try:
193 testMethod = getattr(self, methodName)
194 except AttributeError:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000195 raise ValueError("no such test method in %s: %s" %
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000196 (self.__class__, methodName))
197 self._testMethodDoc = testMethod.__doc__
198 self._cleanups = []
199
200 # Map types to custom assertEqual functions that will compare
201 # instances of said type in more detail to generate a more useful
202 # error message.
203 self._type_equality_funcs = {}
204 self.addTypeEqualityFunc(dict, self.assertDictEqual)
205 self.addTypeEqualityFunc(list, self.assertListEqual)
206 self.addTypeEqualityFunc(tuple, self.assertTupleEqual)
207 self.addTypeEqualityFunc(set, self.assertSetEqual)
208 self.addTypeEqualityFunc(frozenset, self.assertSetEqual)
Michael Foord02834952010-02-08 23:10:39 +0000209 self.addTypeEqualityFunc(str, self.assertMultiLineEqual)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000210
211 def addTypeEqualityFunc(self, typeobj, function):
212 """Add a type specific assertEqual style function to compare a type.
213
214 This method is for use by TestCase subclasses that need to register
215 their own type equality functions to provide nicer error messages.
216
217 Args:
218 typeobj: The data type to call this function on when both values
219 are of the same type in assertEqual().
220 function: The callable taking two arguments and an optional
221 msg= argument that raises self.failureException with a
222 useful error message when the two arguments are not equal.
223 """
Benjamin Peterson8f326b22009-12-13 02:10:36 +0000224 self._type_equality_funcs[typeobj] = function
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000225
226 def addCleanup(self, function, *args, **kwargs):
227 """Add a function, with arguments, to be called when the test is
228 completed. Functions added are called on a LIFO basis and are
229 called after tearDown on test failure or success.
230
231 Cleanup items are called even if setUp fails (unlike tearDown)."""
232 self._cleanups.append((function, args, kwargs))
233
234 def setUp(self):
235 "Hook method for setting up the test fixture before exercising it."
236 pass
237
238 def tearDown(self):
239 "Hook method for deconstructing the test fixture after testing it."
240 pass
241
Benjamin Peterson847a4112010-03-14 15:04:17 +0000242 @classmethod
243 def setUpClass(cls):
244 "Hook method for setting up class fixture before running tests in the class."
245
246 @classmethod
247 def tearDownClass(cls):
248 "Hook method for deconstructing the class fixture after running all tests in the class."
249
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000250 def countTestCases(self):
251 return 1
252
253 def defaultTestResult(self):
254 return result.TestResult()
255
256 def shortDescription(self):
Michael Foord34c94622010-02-10 15:51:42 +0000257 """Returns a one-line description of the test, or None if no
258 description has been provided.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000259
Michael Foord34c94622010-02-10 15:51:42 +0000260 The default implementation of this method returns the first line of
261 the specified test method's docstring.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000262 """
Michael Foord34c94622010-02-10 15:51:42 +0000263 doc = self._testMethodDoc
264 return doc and doc.split("\n")[0].strip() or None
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000265
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000266
267 def id(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000268 return "%s.%s" % (strclass(self.__class__), self._testMethodName)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000269
270 def __eq__(self, other):
271 if type(self) is not type(other):
272 return NotImplemented
273
274 return self._testMethodName == other._testMethodName
275
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000276 def __hash__(self):
277 return hash((type(self), self._testMethodName))
278
279 def __str__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000280 return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000281
282 def __repr__(self):
283 return "<%s testMethod=%s>" % \
Benjamin Peterson847a4112010-03-14 15:04:17 +0000284 (strclass(self.__class__), self._testMethodName)
285
286 def _addSkip(self, result, reason):
287 addSkip = getattr(result, 'addSkip', None)
288 if addSkip is not None:
289 addSkip(self, reason)
290 else:
291 warnings.warn("TestResult has no addSkip method, skips not reported",
292 RuntimeWarning, 2)
293 result.addSuccess(self)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000294
295 def run(self, result=None):
296 orig_result = result
297 if result is None:
298 result = self.defaultTestResult()
299 startTestRun = getattr(result, 'startTestRun', None)
300 if startTestRun is not None:
301 startTestRun()
302
303 self._resultForDoCleanups = result
304 result.startTest(self)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000305
306 testMethod = getattr(self, self._testMethodName)
307 if (getattr(self.__class__, "__unittest_skip__", False) or
308 getattr(testMethod, "__unittest_skip__", False)):
309 # If the class or method was skipped.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000310 try:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000311 skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
312 or getattr(testMethod, '__unittest_skip_why__', ''))
313 self._addSkip(result, skip_why)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000314 finally:
315 result.stopTest(self)
316 return
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000317 try:
318 success = False
319 try:
320 self.setUp()
321 except SkipTest as e:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000322 self._addSkip(result, str(e))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000323 except Exception:
324 result.addError(self, sys.exc_info())
325 else:
326 try:
327 testMethod()
328 except self.failureException:
329 result.addFailure(self, sys.exc_info())
330 except _ExpectedFailure as e:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000331 addExpectedFailure = getattr(result, 'addExpectedFailure', None)
332 if addExpectedFailure is not None:
333 addExpectedFailure(self, e.exc_info)
334 else:
335 warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
336 RuntimeWarning)
337 result.addSuccess(self)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000338 except _UnexpectedSuccess:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000339 addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
340 if addUnexpectedSuccess is not None:
341 addUnexpectedSuccess(self)
342 else:
343 warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures",
344 RuntimeWarning)
345 result.addFailure(self, sys.exc_info())
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000346 except SkipTest as e:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000347 self._addSkip(result, str(e))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000348 except Exception:
349 result.addError(self, sys.exc_info())
350 else:
351 success = True
352
353 try:
354 self.tearDown()
355 except Exception:
356 result.addError(self, sys.exc_info())
357 success = False
358
359 cleanUpSuccess = self.doCleanups()
360 success = success and cleanUpSuccess
361 if success:
362 result.addSuccess(self)
363 finally:
364 result.stopTest(self)
365 if orig_result is None:
366 stopTestRun = getattr(result, 'stopTestRun', None)
367 if stopTestRun is not None:
368 stopTestRun()
369
370 def doCleanups(self):
371 """Execute all cleanup functions. Normally called for you after
372 tearDown."""
373 result = self._resultForDoCleanups
374 ok = True
375 while self._cleanups:
376 function, args, kwargs = self._cleanups.pop(-1)
377 try:
378 function(*args, **kwargs)
379 except Exception:
380 ok = False
381 result.addError(self, sys.exc_info())
382 return ok
383
384 def __call__(self, *args, **kwds):
385 return self.run(*args, **kwds)
386
387 def debug(self):
388 """Run the test without collecting errors in a TestResult"""
389 self.setUp()
390 getattr(self, self._testMethodName)()
391 self.tearDown()
Michael Foordb8748742010-06-10 16:16:08 +0000392 while self._cleanups:
393 function, args, kwargs = self._cleanups.pop(-1)
394 function(*args, **kwargs)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000395
396 def skipTest(self, reason):
397 """Skip this test."""
398 raise SkipTest(reason)
399
400 def fail(self, msg=None):
401 """Fail immediately, with the given message."""
402 raise self.failureException(msg)
403
404 def assertFalse(self, expr, msg=None):
405 "Fail the test if the expression is true."
406 if expr:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000407 msg = self._formatMessage(msg, "%s is not False" % safe_repr(expr))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000408 raise self.failureException(msg)
409
410 def assertTrue(self, expr, msg=None):
411 """Fail the test unless the expression is true."""
412 if not expr:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000413 msg = self._formatMessage(msg, "%s is not True" % safe_repr(expr))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000414 raise self.failureException(msg)
415
416 def _formatMessage(self, msg, standardMsg):
417 """Honour the longMessage attribute when generating failure messages.
418 If longMessage is False this means:
419 * Use only an explicit message if it is provided
420 * Otherwise use the standard message for the assert
421
422 If longMessage is True:
423 * Use the standard message
424 * If an explicit message is provided, plus ' : ' and the explicit message
425 """
426 if not self.longMessage:
427 return msg or standardMsg
428 if msg is None:
429 return standardMsg
Benjamin Peterson847a4112010-03-14 15:04:17 +0000430 try:
431 # don't switch to '{}' formatting in Python 2.X
432 # it changes the way unicode input is handled
433 return '%s : %s' % (standardMsg, msg)
434 except UnicodeDecodeError:
435 return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000436
437
438 def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
439 """Fail unless an exception of class excClass is thrown
440 by callableObj when invoked with arguments args and keyword
441 arguments kwargs. If a different type of exception is
442 thrown, it will not be caught, and the test case will be
443 deemed to have suffered an error, exactly as for an
444 unexpected exception.
445
446 If called with callableObj omitted or None, will return a
447 context object used like this::
448
Michael Foord1c42b122010-02-05 22:58:21 +0000449 with self.assertRaises(SomeException):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000450 do_something()
Michael Foord1c42b122010-02-05 22:58:21 +0000451
452 The context manager keeps a reference to the exception as
Ezio Melotti49008232010-02-08 21:57:48 +0000453 the 'exception' attribute. This allows you to inspect the
Michael Foord1c42b122010-02-05 22:58:21 +0000454 exception after the assertion::
455
456 with self.assertRaises(SomeException) as cm:
457 do_something()
Ezio Melotti49008232010-02-08 21:57:48 +0000458 the_exception = cm.exception
Michael Foordb57ac6d2010-02-05 23:26:29 +0000459 self.assertEqual(the_exception.error_code, 3)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000460 """
461 context = _AssertRaisesContext(excClass, self, callableObj)
462 if callableObj is None:
463 return context
464 with context:
465 callableObj(*args, **kwargs)
466
467 def _getAssertEqualityFunc(self, first, second):
468 """Get a detailed comparison function for the types of the two args.
469
470 Returns: A callable accepting (first, second, msg=None) that will
471 raise a failure exception if first != second with a useful human
472 readable error message for those types.
473 """
474 #
475 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
476 # and vice versa. I opted for the conservative approach in case
477 # subclasses are not intended to be compared in detail to their super
478 # class instances using a type equality func. This means testing
479 # subtypes won't automagically use the detailed comparison. Callers
480 # should use their type specific assertSpamEqual method to compare
481 # subclasses if the detailed comparison is desired and appropriate.
482 # See the discussion in http://bugs.python.org/issue2578.
483 #
484 if type(first) is type(second):
485 asserter = self._type_equality_funcs.get(type(first))
486 if asserter is not None:
Benjamin Peterson8f326b22009-12-13 02:10:36 +0000487 return asserter
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000488
489 return self._baseAssertEqual
490
491 def _baseAssertEqual(self, first, second, msg=None):
492 """The default assertEqual implementation, not type specific."""
493 if not first == second:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000494 standardMsg = '%s != %s' % (safe_repr(first), safe_repr(second))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000495 msg = self._formatMessage(msg, standardMsg)
496 raise self.failureException(msg)
497
498 def assertEqual(self, first, second, msg=None):
499 """Fail if the two objects are unequal as determined by the '=='
500 operator.
501 """
502 assertion_func = self._getAssertEqualityFunc(first, second)
503 assertion_func(first, second, msg=msg)
504
505 def assertNotEqual(self, first, second, msg=None):
506 """Fail if the two objects are equal as determined by the '=='
507 operator.
508 """
509 if not first != second:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000510 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
511 safe_repr(second)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000512 raise self.failureException(msg)
513
Benjamin Petersonb48af542010-04-11 20:43:16 +0000514 def assertAlmostEqual(self, first, second, *, places=None, msg=None,
515 delta=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000516 """Fail if the two objects are unequal as determined by their
517 difference rounded to the given number of decimal places
Benjamin Petersonb48af542010-04-11 20:43:16 +0000518 (default 7) and comparing to zero, or by comparing that the
519 between the two objects is more than the given delta.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000520
521 Note that decimal places (from zero) are usually not the same
522 as significant digits (measured from the most signficant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000523
524 If the two objects compare equal then they will automatically
525 compare almost equal.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000526 """
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000527 if first == second:
Benjamin Petersonb48af542010-04-11 20:43:16 +0000528 # shortcut
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000529 return
Benjamin Petersonb48af542010-04-11 20:43:16 +0000530 if delta is not None and places is not None:
531 raise TypeError("specify delta or places not both")
532
533 if delta is not None:
534 if abs(first - second) <= delta:
535 return
536
537 standardMsg = '%s != %s within %s delta' % (safe_repr(first),
538 safe_repr(second),
539 safe_repr(delta))
540 else:
541 if places is None:
542 places = 7
543
544 if round(abs(second-first), places) == 0:
545 return
546
Benjamin Peterson847a4112010-03-14 15:04:17 +0000547 standardMsg = '%s != %s within %r places' % (safe_repr(first),
548 safe_repr(second),
549 places)
Benjamin Petersonb48af542010-04-11 20:43:16 +0000550 msg = self._formatMessage(msg, standardMsg)
551 raise self.failureException(msg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000552
Benjamin Petersonb48af542010-04-11 20:43:16 +0000553 def assertNotAlmostEqual(self, first, second, *, places=None, msg=None,
554 delta=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000555 """Fail if the two objects are equal as determined by their
556 difference rounded to the given number of decimal places
Benjamin Petersonb48af542010-04-11 20:43:16 +0000557 (default 7) and comparing to zero, or by comparing that the
558 between the two objects is less than the given delta.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000559
560 Note that decimal places (from zero) are usually not the same
561 as significant digits (measured from the most signficant digit).
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000562
563 Objects that are equal automatically fail.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000564 """
Benjamin Petersonb48af542010-04-11 20:43:16 +0000565 if delta is not None and places is not None:
566 raise TypeError("specify delta or places not both")
567 if delta is not None:
568 if not (first == second) and abs(first - second) > delta:
569 return
570 standardMsg = '%s == %s within %s delta' % (safe_repr(first),
571 safe_repr(second),
572 safe_repr(delta))
573 else:
574 if places is None:
575 places = 7
576 if not (first == second) and round(abs(second-first), places) != 0:
577 return
Benjamin Peterson847a4112010-03-14 15:04:17 +0000578 standardMsg = '%s == %s within %r places' % (safe_repr(first),
Benjamin Petersonb48af542010-04-11 20:43:16 +0000579 safe_repr(second),
580 places)
581
582 msg = self._formatMessage(msg, standardMsg)
583 raise self.failureException(msg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000584
585 # Synonyms for assertion methods
586
587 # The plurals are undocumented. Keep them that way to discourage use.
588 # Do not add more. Do not remove.
589 # Going through a deprecation cycle on these would annoy many people.
590 assertEquals = assertEqual
591 assertNotEquals = assertNotEqual
592 assertAlmostEquals = assertAlmostEqual
593 assertNotAlmostEquals = assertNotAlmostEqual
Michael Foord0e31b992010-02-10 15:52:56 +0000594 assert_ = assertTrue
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000595
596 # These fail* assertion method names are pending deprecation and will
597 # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
598 def _deprecate(original_func):
599 def deprecated_func(*args, **kwargs):
600 warnings.warn(
601 'Please use {0} instead.'.format(original_func.__name__),
602 DeprecationWarning, 2)
603 return original_func(*args, **kwargs)
604 return deprecated_func
605
606 failUnlessEqual = _deprecate(assertEqual)
607 failIfEqual = _deprecate(assertNotEqual)
608 failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
609 failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
610 failUnless = _deprecate(assertTrue)
611 failUnlessRaises = _deprecate(assertRaises)
612 failIf = _deprecate(assertFalse)
613
Michael Foord085dfd32010-06-05 12:17:02 +0000614 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000615 """An equality assertion for ordered sequences (like lists and tuples).
616
R. David Murrayad13f222010-01-29 22:17:58 +0000617 For the purposes of this function, a valid ordered sequence type is one
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000618 which can be indexed, has a length, and has an equality operator.
619
620 Args:
621 seq1: The first sequence to compare.
622 seq2: The second sequence to compare.
623 seq_type: The expected datatype of the sequences, or None if no
624 datatype should be enforced.
625 msg: Optional message to use on failure instead of a list of
626 differences.
627 """
628 if seq_type != None:
629 seq_type_name = seq_type.__name__
630 if not isinstance(seq1, seq_type):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000631 raise self.failureException('First sequence is not a %s: %s'
632 % (seq_type_name, safe_repr(seq1)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000633 if not isinstance(seq2, seq_type):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000634 raise self.failureException('Second sequence is not a %s: %s'
635 % (seq_type_name, safe_repr(seq2)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000636 else:
637 seq_type_name = "sequence"
638
639 differing = None
640 try:
641 len1 = len(seq1)
642 except (TypeError, NotImplementedError):
643 differing = 'First %s has no length. Non-sequence?' % (
644 seq_type_name)
645
646 if differing is None:
647 try:
648 len2 = len(seq2)
649 except (TypeError, NotImplementedError):
650 differing = 'Second %s has no length. Non-sequence?' % (
651 seq_type_name)
652
653 if differing is None:
654 if seq1 == seq2:
655 return
656
Benjamin Peterson847a4112010-03-14 15:04:17 +0000657 seq1_repr = safe_repr(seq1)
658 seq2_repr = safe_repr(seq2)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000659 if len(seq1_repr) > 30:
660 seq1_repr = seq1_repr[:30] + '...'
661 if len(seq2_repr) > 30:
662 seq2_repr = seq2_repr[:30] + '...'
663 elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
664 differing = '%ss differ: %s != %s\n' % elements
665
666 for i in range(min(len1, len2)):
667 try:
668 item1 = seq1[i]
669 except (TypeError, IndexError, NotImplementedError):
670 differing += ('\nUnable to index element %d of first %s\n' %
671 (i, seq_type_name))
672 break
673
674 try:
675 item2 = seq2[i]
676 except (TypeError, IndexError, NotImplementedError):
677 differing += ('\nUnable to index element %d of second %s\n' %
678 (i, seq_type_name))
679 break
680
681 if item1 != item2:
682 differing += ('\nFirst differing element %d:\n%s\n%s\n' %
683 (i, item1, item2))
684 break
685 else:
686 if (len1 == len2 and seq_type is None and
687 type(seq1) != type(seq2)):
688 # The sequences are the same, but have differing types.
689 return
690
691 if len1 > len2:
692 differing += ('\nFirst %s contains %d additional '
693 'elements.\n' % (seq_type_name, len1 - len2))
694 try:
695 differing += ('First extra element %d:\n%s\n' %
696 (len2, seq1[len2]))
697 except (TypeError, IndexError, NotImplementedError):
698 differing += ('Unable to index element %d '
699 'of first %s\n' % (len2, seq_type_name))
700 elif len1 < len2:
701 differing += ('\nSecond %s contains %d additional '
702 'elements.\n' % (seq_type_name, len2 - len1))
703 try:
704 differing += ('First extra element %d:\n%s\n' %
705 (len1, seq2[len1]))
706 except (TypeError, IndexError, NotImplementedError):
707 differing += ('Unable to index element %d '
708 'of second %s\n' % (len1, seq_type_name))
Michael Foord2034d9a2010-06-05 11:27:52 +0000709 standardMsg = differing
710 diffMsg = '\n' + '\n'.join(
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000711 difflib.ndiff(pprint.pformat(seq1).splitlines(),
712 pprint.pformat(seq2).splitlines()))
Michael Foord085dfd32010-06-05 12:17:02 +0000713
714 standardMsg = self._truncateMessage(standardMsg, diffMsg)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000715 msg = self._formatMessage(msg, standardMsg)
716 self.fail(msg)
717
Michael Foord085dfd32010-06-05 12:17:02 +0000718 def _truncateMessage(self, message, diff):
719 max_diff = self.maxDiff
720 if max_diff is None or len(diff) <= max_diff:
721 return message + diff
Michael Foord9dad32e2010-06-05 13:49:56 +0000722 return message + (DIFF_OMITTED % len(diff))
Michael Foord085dfd32010-06-05 12:17:02 +0000723
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000724 def assertListEqual(self, list1, list2, msg=None):
725 """A list-specific equality assertion.
726
727 Args:
728 list1: The first list to compare.
729 list2: The second list to compare.
730 msg: Optional message to use on failure instead of a list of
731 differences.
732
733 """
734 self.assertSequenceEqual(list1, list2, msg, seq_type=list)
735
736 def assertTupleEqual(self, tuple1, tuple2, msg=None):
737 """A tuple-specific equality assertion.
738
739 Args:
740 tuple1: The first tuple to compare.
741 tuple2: The second tuple to compare.
742 msg: Optional message to use on failure instead of a list of
743 differences.
744 """
745 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
746
747 def assertSetEqual(self, set1, set2, msg=None):
748 """A set-specific equality assertion.
749
750 Args:
751 set1: The first set to compare.
752 set2: The second set to compare.
753 msg: Optional message to use on failure instead of a list of
754 differences.
755
Michael Foord91c9da32010-03-20 17:21:27 +0000756 assertSetEqual uses ducktyping to support different types of sets, and
757 is optimized for sets specifically (parameters must support a
758 difference method).
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000759 """
760 try:
761 difference1 = set1.difference(set2)
762 except TypeError as e:
763 self.fail('invalid type when attempting set difference: %s' % e)
764 except AttributeError as e:
765 self.fail('first argument does not support set difference: %s' % e)
766
767 try:
768 difference2 = set2.difference(set1)
769 except TypeError as e:
770 self.fail('invalid type when attempting set difference: %s' % e)
771 except AttributeError as e:
772 self.fail('second argument does not support set difference: %s' % e)
773
774 if not (difference1 or difference2):
775 return
776
777 lines = []
778 if difference1:
779 lines.append('Items in the first set but not the second:')
780 for item in difference1:
781 lines.append(repr(item))
782 if difference2:
783 lines.append('Items in the second set but not the first:')
784 for item in difference2:
785 lines.append(repr(item))
786
787 standardMsg = '\n'.join(lines)
788 self.fail(self._formatMessage(msg, standardMsg))
789
790 def assertIn(self, member, container, msg=None):
791 """Just like self.assertTrue(a in b), but with a nicer default message."""
792 if member not in container:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000793 standardMsg = '%s not found in %s' % (safe_repr(member),
794 safe_repr(container))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000795 self.fail(self._formatMessage(msg, standardMsg))
796
797 def assertNotIn(self, member, container, msg=None):
798 """Just like self.assertTrue(a not in b), but with a nicer default message."""
799 if member in container:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000800 standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
801 safe_repr(container))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000802 self.fail(self._formatMessage(msg, standardMsg))
803
804 def assertIs(self, expr1, expr2, msg=None):
805 """Just like self.assertTrue(a is b), but with a nicer default message."""
806 if expr1 is not expr2:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000807 standardMsg = '%s is not %s' % (safe_repr(expr1),
808 safe_repr(expr2))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000809 self.fail(self._formatMessage(msg, standardMsg))
810
811 def assertIsNot(self, expr1, expr2, msg=None):
812 """Just like self.assertTrue(a is not b), but with a nicer default message."""
813 if expr1 is expr2:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000814 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000815 self.fail(self._formatMessage(msg, standardMsg))
816
817 def assertDictEqual(self, d1, d2, msg=None):
818 self.assert_(isinstance(d1, dict), 'First argument is not a dictionary')
819 self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary')
820
821 if d1 != d2:
Michael Foordcb11b252010-06-05 13:14:43 +0000822 standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True))
Michael Foord085dfd32010-06-05 12:17:02 +0000823 diff = ('\n' + '\n'.join(difflib.ndiff(
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000824 pprint.pformat(d1).splitlines(),
825 pprint.pformat(d2).splitlines())))
Michael Foordcb11b252010-06-05 13:14:43 +0000826 standardMsg = self._truncateMessage(standardMsg, diff)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000827 self.fail(self._formatMessage(msg, standardMsg))
828
829 def assertDictContainsSubset(self, expected, actual, msg=None):
830 """Checks whether actual is a superset of expected."""
831 missing = []
832 mismatched = []
833 for key, value in expected.items():
834 if key not in actual:
835 missing.append(key)
836 elif value != actual[key]:
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000837 mismatched.append('%s, expected: %s, actual: %s' %
Benjamin Peterson847a4112010-03-14 15:04:17 +0000838 (safe_repr(key), safe_repr(value),
839 safe_repr(actual[key])))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000840
841 if not (missing or mismatched):
842 return
843
844 standardMsg = ''
845 if missing:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000846 standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
847 missing)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000848 if mismatched:
849 if standardMsg:
850 standardMsg += '; '
851 standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
852
853 self.fail(self._formatMessage(msg, standardMsg))
854
855 def assertSameElements(self, expected_seq, actual_seq, msg=None):
856 """An unordered sequence specific comparison.
857
858 Raises with an error message listing which elements of expected_seq
859 are missing from actual_seq and vice versa if any.
Michael Foord1c42b122010-02-05 22:58:21 +0000860
861 Duplicate elements are ignored when comparing *expected_seq* and
862 *actual_seq*. It is the equivalent of ``assertEqual(set(expected),
863 set(actual))`` but it works with sequences of unhashable objects as
864 well.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000865 """
Michael Foord91c9da32010-03-20 17:21:27 +0000866 warnings.warn('assertSameElements is deprecated',
867 DeprecationWarning)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000868 try:
869 expected = set(expected_seq)
870 actual = set(actual_seq)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000871 missing = sorted(expected.difference(actual))
872 unexpected = sorted(actual.difference(expected))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000873 except TypeError:
874 # Fall back to slower list-compare if any of the objects are
875 # not hashable.
876 expected = list(expected_seq)
877 actual = list(actual_seq)
878 try:
879 expected.sort()
880 actual.sort()
881 except TypeError:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000882 missing, unexpected = unorderable_list_difference(expected,
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000883 actual)
Benjamin Peterson847a4112010-03-14 15:04:17 +0000884 else:
885 missing, unexpected = sorted_list_difference(expected, actual)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000886 errors = []
887 if missing:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000888 errors.append('Expected, but missing:\n %s' %
889 safe_repr(missing))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000890 if unexpected:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000891 errors.append('Unexpected, but present:\n %s' %
892 safe_repr(unexpected))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000893 if errors:
894 standardMsg = '\n'.join(errors)
895 self.fail(self._formatMessage(msg, standardMsg))
896
Michael Foord8442a602010-03-20 16:58:04 +0000897
898 def assertItemsEqual(self, expected_seq, actual_seq, msg=None):
899 """An unordered sequence / set specific comparison. It asserts that
900 expected_seq and actual_seq contain the same elements. It is
901 the equivalent of::
902
903 self.assertEqual(sorted(expected_seq), sorted(actual_seq))
904
905 Raises with an error message listing which elements of expected_seq
906 are missing from actual_seq and vice versa if any.
907
908 Asserts that each element has the same count in both sequences.
909 Example:
910 - [0, 1, 1] and [1, 0, 1] compare equal.
911 - [0, 0, 1] and [0, 1] compare unequal.
912 """
913 try:
914 expected = sorted(expected_seq)
915 actual = sorted(actual_seq)
916 except TypeError:
917 # Unsortable items (example: set(), complex(), ...)
918 expected = list(expected_seq)
919 actual = list(actual_seq)
920 missing, unexpected = unorderable_list_difference(expected, actual)
921 else:
922 return self.assertSequenceEqual(expected, actual, msg=msg)
923
924 errors = []
925 if missing:
926 errors.append('Expected, but missing:\n %s' %
927 safe_repr(missing))
928 if unexpected:
929 errors.append('Unexpected, but present:\n %s' %
930 safe_repr(unexpected))
931 if errors:
932 standardMsg = '\n'.join(errors)
933 self.fail(self._formatMessage(msg, standardMsg))
934
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000935 def assertMultiLineEqual(self, first, second, msg=None):
936 """Assert that two multi-line strings are equal."""
937 self.assert_(isinstance(first, str), (
938 'First argument is not a string'))
939 self.assert_(isinstance(second, str), (
940 'Second argument is not a string'))
941
942 if first != second:
Michael Foordc653ce32010-07-10 13:52:22 +0000943 firstlines = first.splitlines(True)
944 secondlines = second.splitlines(True)
945 if len(firstlines) == 1 and first.strip('\r\n') == first:
946 firstlines = [first + '\n']
947 secondlines = [second + '\n']
948 standardMsg = '%s != %s' % (safe_repr(first, True),
949 safe_repr(second, True))
950 diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines))
Michael Foordcb11b252010-06-05 13:14:43 +0000951 standardMsg = self._truncateMessage(standardMsg, diff)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000952 self.fail(self._formatMessage(msg, standardMsg))
953
954 def assertLess(self, a, b, msg=None):
955 """Just like self.assertTrue(a < b), but with a nicer default message."""
956 if not a < b:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000957 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000958 self.fail(self._formatMessage(msg, standardMsg))
959
960 def assertLessEqual(self, a, b, msg=None):
961 """Just like self.assertTrue(a <= b), but with a nicer default message."""
962 if not a <= b:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000963 standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000964 self.fail(self._formatMessage(msg, standardMsg))
965
966 def assertGreater(self, a, b, msg=None):
967 """Just like self.assertTrue(a > b), but with a nicer default message."""
968 if not a > b:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000969 standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000970 self.fail(self._formatMessage(msg, standardMsg))
971
972 def assertGreaterEqual(self, a, b, msg=None):
973 """Just like self.assertTrue(a >= b), but with a nicer default message."""
974 if not a >= b:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000975 standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000976 self.fail(self._formatMessage(msg, standardMsg))
977
978 def assertIsNone(self, obj, msg=None):
979 """Same as self.assertTrue(obj is None), with a nicer default message."""
980 if obj is not None:
Benjamin Peterson847a4112010-03-14 15:04:17 +0000981 standardMsg = '%s is not None' % (safe_repr(obj),)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000982 self.fail(self._formatMessage(msg, standardMsg))
983
984 def assertIsNotNone(self, obj, msg=None):
985 """Included for symmetry with assertIsNone."""
986 if obj is None:
987 standardMsg = 'unexpectedly None'
988 self.fail(self._formatMessage(msg, standardMsg))
989
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000990 def assertIsInstance(self, obj, cls, msg=None):
991 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
992 default message."""
993 if not isinstance(obj, cls):
Benjamin Peterson847a4112010-03-14 15:04:17 +0000994 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
Benjamin Peterson6e8c7572009-10-04 20:19:21 +0000995 self.fail(self._formatMessage(msg, standardMsg))
996
997 def assertNotIsInstance(self, obj, cls, msg=None):
998 """Included for symmetry with assertIsInstance."""
999 if isinstance(obj, cls):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001000 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
Benjamin Peterson6e8c7572009-10-04 20:19:21 +00001001 self.fail(self._formatMessage(msg, standardMsg))
1002
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001003 def assertRaisesRegexp(self, expected_exception, expected_regexp,
1004 callable_obj=None, *args, **kwargs):
1005 """Asserts that the message in a raised exception matches a regexp.
1006
1007 Args:
1008 expected_exception: Exception class expected to be raised.
1009 expected_regexp: Regexp (re pattern object or string) expected
1010 to be found in error message.
1011 callable_obj: Function to be called.
1012 args: Extra args.
1013 kwargs: Extra kwargs.
1014 """
1015 context = _AssertRaisesContext(expected_exception, self, callable_obj,
1016 expected_regexp)
1017 if callable_obj is None:
1018 return context
1019 with context:
1020 callable_obj(*args, **kwargs)
1021
Georg Brandl89fad142010-03-14 10:23:39 +00001022 def assertRegexpMatches(self, text, expected_regexp, msg=None):
Michael Foorde3ef5f12010-05-08 16:46:14 +00001023 """Fail the test unless the text matches the regular expression."""
Georg Brandl89fad142010-03-14 10:23:39 +00001024 if isinstance(expected_regexp, (str, bytes)):
1025 expected_regexp = re.compile(expected_regexp)
1026 if not expected_regexp.search(text):
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001027 msg = msg or "Regexp didn't match"
Georg Brandl89fad142010-03-14 10:23:39 +00001028 msg = '%s: %r not found in %r' % (msg, expected_regexp.pattern, text)
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001029 raise self.failureException(msg)
1030
Benjamin Petersonb48af542010-04-11 20:43:16 +00001031 def assertNotRegexpMatches(self, text, unexpected_regexp, msg=None):
Michael Foorde3ef5f12010-05-08 16:46:14 +00001032 """Fail the test if the text matches the regular expression."""
Benjamin Petersonb48af542010-04-11 20:43:16 +00001033 if isinstance(unexpected_regexp, (str, bytes)):
1034 unexpected_regexp = re.compile(unexpected_regexp)
1035 match = unexpected_regexp.search(text)
1036 if match:
1037 msg = msg or "Regexp matched"
1038 msg = '%s: %r matches %r in %r' % (msg,
1039 text[match.start():match.end()],
1040 unexpected_regexp.pattern,
1041 text)
1042 raise self.failureException(msg)
1043
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001044
1045class FunctionTestCase(TestCase):
1046 """A test case that wraps a test function.
1047
1048 This is useful for slipping pre-existing test functions into the
1049 unittest framework. Optionally, set-up and tidy-up functions can be
1050 supplied. As with TestCase, the tidy-up ('tearDown') function will
1051 always be called if the set-up ('setUp') function ran successfully.
1052 """
1053
1054 def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
1055 super(FunctionTestCase, self).__init__()
1056 self._setUpFunc = setUp
1057 self._tearDownFunc = tearDown
1058 self._testFunc = testFunc
1059 self._description = description
1060
1061 def setUp(self):
1062 if self._setUpFunc is not None:
1063 self._setUpFunc()
1064
1065 def tearDown(self):
1066 if self._tearDownFunc is not None:
1067 self._tearDownFunc()
1068
1069 def runTest(self):
1070 self._testFunc()
1071
1072 def id(self):
1073 return self._testFunc.__name__
1074
1075 def __eq__(self, other):
1076 if not isinstance(other, self.__class__):
1077 return NotImplemented
1078
1079 return self._setUpFunc == other._setUpFunc and \
1080 self._tearDownFunc == other._tearDownFunc and \
1081 self._testFunc == other._testFunc and \
1082 self._description == other._description
1083
1084 def __ne__(self, other):
1085 return not self == other
1086
1087 def __hash__(self):
1088 return hash((type(self), self._setUpFunc, self._tearDownFunc,
1089 self._testFunc, self._description))
1090
1091 def __str__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001092 return "%s (%s)" % (strclass(self.__class__),
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001093 self._testFunc.__name__)
1094
1095 def __repr__(self):
Benjamin Peterson847a4112010-03-14 15:04:17 +00001096 return "<%s tec=%s>" % (strclass(self.__class__),
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001097 self._testFunc)
1098
1099 def shortDescription(self):
1100 if self._description is not None:
1101 return self._description
1102 doc = self._testFunc.__doc__
1103 return doc and doc.split("\n")[0].strip() or None