• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""Test case implementation"""
2
3import sys
4import functools
5import difflib
6import pprint
7import re
8import warnings
9import collections
10import contextlib
11import traceback
12import time
13import types
14
15from . import result
16from .util import (strclass, safe_repr, _count_diff_all_purpose,
17                   _count_diff_hashable, _common_shorten_repr)
18
19__unittest = True
20
21_subtest_msg_sentinel = object()
22
23DIFF_OMITTED = ('\nDiff is %s characters long. '
24                 'Set self.maxDiff to None to see it.')
25
26class SkipTest(Exception):
27    """
28    Raise this exception in a test to skip it.
29
30    Usually you can use TestCase.skipTest() or one of the skipping decorators
31    instead of raising this directly.
32    """
33
34class _ShouldStop(Exception):
35    """
36    The test should stop.
37    """
38
39class _UnexpectedSuccess(Exception):
40    """
41    The test was supposed to fail, but it didn't!
42    """
43
44
45class _Outcome(object):
46    def __init__(self, result=None):
47        self.expecting_failure = False
48        self.result = result
49        self.result_supports_subtests = hasattr(result, "addSubTest")
50        self.success = True
51        self.expectedFailure = None
52
53    @contextlib.contextmanager
54    def testPartExecutor(self, test_case, subTest=False):
55        old_success = self.success
56        self.success = True
57        try:
58            yield
59        except KeyboardInterrupt:
60            raise
61        except SkipTest as e:
62            self.success = False
63            _addSkip(self.result, test_case, str(e))
64        except _ShouldStop:
65            pass
66        except:
67            exc_info = sys.exc_info()
68            if self.expecting_failure:
69                self.expectedFailure = exc_info
70            else:
71                self.success = False
72                if subTest:
73                    self.result.addSubTest(test_case.test_case, test_case, exc_info)
74                else:
75                    _addError(self.result, test_case, exc_info)
76            # explicitly break a reference cycle:
77            # exc_info -> frame -> exc_info
78            exc_info = None
79        else:
80            if subTest and self.success:
81                self.result.addSubTest(test_case.test_case, test_case, None)
82        finally:
83            self.success = self.success and old_success
84
85
86def _addSkip(result, test_case, reason):
87    addSkip = getattr(result, 'addSkip', None)
88    if addSkip is not None:
89        addSkip(test_case, reason)
90    else:
91        warnings.warn("TestResult has no addSkip method, skips not reported",
92                      RuntimeWarning, 2)
93        result.addSuccess(test_case)
94
95def _addError(result, test, exc_info):
96    if result is not None and exc_info is not None:
97        if issubclass(exc_info[0], test.failureException):
98            result.addFailure(test, exc_info)
99        else:
100            result.addError(test, exc_info)
101
102def _id(obj):
103    return obj
104
105
106def _enter_context(cm, addcleanup):
107    # We look up the special methods on the type to match the with
108    # statement.
109    cls = type(cm)
110    try:
111        enter = cls.__enter__
112        exit = cls.__exit__
113    except AttributeError:
114        raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does "
115                        f"not support the context manager protocol") from None
116    result = enter(cm)
117    addcleanup(exit, cm, None, None, None)
118    return result
119
120
121_module_cleanups = []
122def addModuleCleanup(function, /, *args, **kwargs):
123    """Same as addCleanup, except the cleanup items are called even if
124    setUpModule fails (unlike tearDownModule)."""
125    _module_cleanups.append((function, args, kwargs))
126
127def enterModuleContext(cm):
128    """Same as enterContext, but module-wide."""
129    return _enter_context(cm, addModuleCleanup)
130
131
132def doModuleCleanups():
133    """Execute all module cleanup functions. Normally called for you after
134    tearDownModule."""
135    exceptions = []
136    while _module_cleanups:
137        function, args, kwargs = _module_cleanups.pop()
138        try:
139            function(*args, **kwargs)
140        except Exception as exc:
141            exceptions.append(exc)
142    if exceptions:
143        # Swallows all but first exception. If a multi-exception handler
144        # gets written we should use that here instead.
145        raise exceptions[0]
146
147
148def skip(reason):
149    """
150    Unconditionally skip a test.
151    """
152    def decorator(test_item):
153        if not isinstance(test_item, type):
154            @functools.wraps(test_item)
155            def skip_wrapper(*args, **kwargs):
156                raise SkipTest(reason)
157            test_item = skip_wrapper
158
159        test_item.__unittest_skip__ = True
160        test_item.__unittest_skip_why__ = reason
161        return test_item
162    if isinstance(reason, types.FunctionType):
163        test_item = reason
164        reason = ''
165        return decorator(test_item)
166    return decorator
167
168def skipIf(condition, reason):
169    """
170    Skip a test if the condition is true.
171    """
172    if condition:
173        return skip(reason)
174    return _id
175
176def skipUnless(condition, reason):
177    """
178    Skip a test unless the condition is true.
179    """
180    if not condition:
181        return skip(reason)
182    return _id
183
184def expectedFailure(test_item):
185    test_item.__unittest_expecting_failure__ = True
186    return test_item
187
188def _is_subtype(expected, basetype):
189    if isinstance(expected, tuple):
190        return all(_is_subtype(e, basetype) for e in expected)
191    return isinstance(expected, type) and issubclass(expected, basetype)
192
193class _BaseTestCaseContext:
194
195    def __init__(self, test_case):
196        self.test_case = test_case
197
198    def _raiseFailure(self, standardMsg):
199        msg = self.test_case._formatMessage(self.msg, standardMsg)
200        raise self.test_case.failureException(msg)
201
202class _AssertRaisesBaseContext(_BaseTestCaseContext):
203
204    def __init__(self, expected, test_case, expected_regex=None):
205        _BaseTestCaseContext.__init__(self, test_case)
206        self.expected = expected
207        self.test_case = test_case
208        if expected_regex is not None:
209            expected_regex = re.compile(expected_regex)
210        self.expected_regex = expected_regex
211        self.obj_name = None
212        self.msg = None
213
214    def handle(self, name, args, kwargs):
215        """
216        If args is empty, assertRaises/Warns is being used as a
217        context manager, so check for a 'msg' kwarg and return self.
218        If args is not empty, call a callable passing positional and keyword
219        arguments.
220        """
221        try:
222            if not _is_subtype(self.expected, self._base_type):
223                raise TypeError('%s() arg 1 must be %s' %
224                                (name, self._base_type_str))
225            if not args:
226                self.msg = kwargs.pop('msg', None)
227                if kwargs:
228                    raise TypeError('%r is an invalid keyword argument for '
229                                    'this function' % (next(iter(kwargs)),))
230                return self
231
232            callable_obj, *args = args
233            try:
234                self.obj_name = callable_obj.__name__
235            except AttributeError:
236                self.obj_name = str(callable_obj)
237            with self:
238                callable_obj(*args, **kwargs)
239        finally:
240            # bpo-23890: manually break a reference cycle
241            self = None
242
243
244class _AssertRaisesContext(_AssertRaisesBaseContext):
245    """A context manager used to implement TestCase.assertRaises* methods."""
246
247    _base_type = BaseException
248    _base_type_str = 'an exception type or tuple of exception types'
249
250    def __enter__(self):
251        return self
252
253    def __exit__(self, exc_type, exc_value, tb):
254        if exc_type is None:
255            try:
256                exc_name = self.expected.__name__
257            except AttributeError:
258                exc_name = str(self.expected)
259            if self.obj_name:
260                self._raiseFailure("{} not raised by {}".format(exc_name,
261                                                                self.obj_name))
262            else:
263                self._raiseFailure("{} not raised".format(exc_name))
264        else:
265            traceback.clear_frames(tb)
266        if not issubclass(exc_type, self.expected):
267            # let unexpected exceptions pass through
268            return False
269        # store exception, without traceback, for later retrieval
270        self.exception = exc_value.with_traceback(None)
271        if self.expected_regex is None:
272            return True
273
274        expected_regex = self.expected_regex
275        if not expected_regex.search(str(exc_value)):
276            self._raiseFailure('"{}" does not match "{}"'.format(
277                     expected_regex.pattern, str(exc_value)))
278        return True
279
280    __class_getitem__ = classmethod(types.GenericAlias)
281
282
283class _AssertWarnsContext(_AssertRaisesBaseContext):
284    """A context manager used to implement TestCase.assertWarns* methods."""
285
286    _base_type = Warning
287    _base_type_str = 'a warning type or tuple of warning types'
288
289    def __enter__(self):
290        # The __warningregistry__'s need to be in a pristine state for tests
291        # to work properly.
292        for v in list(sys.modules.values()):
293            if getattr(v, '__warningregistry__', None):
294                v.__warningregistry__ = {}
295        self.warnings_manager = warnings.catch_warnings(record=True)
296        self.warnings = self.warnings_manager.__enter__()
297        warnings.simplefilter("always", self.expected)
298        return self
299
300    def __exit__(self, exc_type, exc_value, tb):
301        self.warnings_manager.__exit__(exc_type, exc_value, tb)
302        if exc_type is not None:
303            # let unexpected exceptions pass through
304            return
305        try:
306            exc_name = self.expected.__name__
307        except AttributeError:
308            exc_name = str(self.expected)
309        first_matching = None
310        for m in self.warnings:
311            w = m.message
312            if not isinstance(w, self.expected):
313                continue
314            if first_matching is None:
315                first_matching = w
316            if (self.expected_regex is not None and
317                not self.expected_regex.search(str(w))):
318                continue
319            # store warning for later retrieval
320            self.warning = w
321            self.filename = m.filename
322            self.lineno = m.lineno
323            return
324        # Now we simply try to choose a helpful failure message
325        if first_matching is not None:
326            self._raiseFailure('"{}" does not match "{}"'.format(
327                     self.expected_regex.pattern, str(first_matching)))
328        if self.obj_name:
329            self._raiseFailure("{} not triggered by {}".format(exc_name,
330                                                               self.obj_name))
331        else:
332            self._raiseFailure("{} not triggered".format(exc_name))
333
334
335class _AssertNotWarnsContext(_AssertWarnsContext):
336
337    def __exit__(self, exc_type, exc_value, tb):
338        self.warnings_manager.__exit__(exc_type, exc_value, tb)
339        if exc_type is not None:
340            # let unexpected exceptions pass through
341            return
342        try:
343            exc_name = self.expected.__name__
344        except AttributeError:
345            exc_name = str(self.expected)
346        for m in self.warnings:
347            w = m.message
348            if isinstance(w, self.expected):
349                self._raiseFailure(f"{exc_name} triggered")
350
351
352class _OrderedChainMap(collections.ChainMap):
353    def __iter__(self):
354        seen = set()
355        for mapping in self.maps:
356            for k in mapping:
357                if k not in seen:
358                    seen.add(k)
359                    yield k
360
361
362class TestCase(object):
363    """A class whose instances are single test cases.
364
365    By default, the test code itself should be placed in a method named
366    'runTest'.
367
368    If the fixture may be used for many test cases, create as
369    many test methods as are needed. When instantiating such a TestCase
370    subclass, specify in the constructor arguments the name of the test method
371    that the instance is to execute.
372
373    Test authors should subclass TestCase for their own tests. Construction
374    and deconstruction of the test's environment ('fixture') can be
375    implemented by overriding the 'setUp' and 'tearDown' methods respectively.
376
377    If it is necessary to override the __init__ method, the base class
378    __init__ method must always be called. It is important that subclasses
379    should not change the signature of their __init__ method, since instances
380    of the classes are instantiated automatically by parts of the framework
381    in order to be run.
382
383    When subclassing TestCase, you can set these attributes:
384    * failureException: determines which exception will be raised when
385        the instance's assertion methods fail; test methods raising this
386        exception will be deemed to have 'failed' rather than 'errored'.
387    * longMessage: determines whether long messages (including repr of
388        objects used in assert methods) will be printed on failure in *addition*
389        to any explicit message passed.
390    * maxDiff: sets the maximum length of a diff in failure messages
391        by assert methods using difflib. It is looked up as an instance
392        attribute so can be configured by individual tests if required.
393    """
394
395    failureException = AssertionError
396
397    longMessage = True
398
399    maxDiff = 80*8
400
401    # If a string is longer than _diffThreshold, use normal comparison instead
402    # of difflib.  See #11763.
403    _diffThreshold = 2**16
404
405    def __init_subclass__(cls, *args, **kwargs):
406        # Attribute used by TestSuite for classSetUp
407        cls._classSetupFailed = False
408        cls._class_cleanups = []
409        super().__init_subclass__(*args, **kwargs)
410
411    def __init__(self, methodName='runTest'):
412        """Create an instance of the class that will use the named test
413           method when executed. Raises a ValueError if the instance does
414           not have a method with the specified name.
415        """
416        self._testMethodName = methodName
417        self._outcome = None
418        self._testMethodDoc = 'No test'
419        try:
420            testMethod = getattr(self, methodName)
421        except AttributeError:
422            if methodName != 'runTest':
423                # we allow instantiation with no explicit method name
424                # but not an *incorrect* or missing method name
425                raise ValueError("no such test method in %s: %s" %
426                      (self.__class__, methodName))
427        else:
428            self._testMethodDoc = testMethod.__doc__
429        self._cleanups = []
430        self._subtest = None
431
432        # Map types to custom assertEqual functions that will compare
433        # instances of said type in more detail to generate a more useful
434        # error message.
435        self._type_equality_funcs = {}
436        self.addTypeEqualityFunc(dict, 'assertDictEqual')
437        self.addTypeEqualityFunc(list, 'assertListEqual')
438        self.addTypeEqualityFunc(tuple, 'assertTupleEqual')
439        self.addTypeEqualityFunc(set, 'assertSetEqual')
440        self.addTypeEqualityFunc(frozenset, 'assertSetEqual')
441        self.addTypeEqualityFunc(str, 'assertMultiLineEqual')
442
443    def addTypeEqualityFunc(self, typeobj, function):
444        """Add a type specific assertEqual style function to compare a type.
445
446        This method is for use by TestCase subclasses that need to register
447        their own type equality functions to provide nicer error messages.
448
449        Args:
450            typeobj: The data type to call this function on when both values
451                    are of the same type in assertEqual().
452            function: The callable taking two arguments and an optional
453                    msg= argument that raises self.failureException with a
454                    useful error message when the two arguments are not equal.
455        """
456        self._type_equality_funcs[typeobj] = function
457
458    def addCleanup(self, function, /, *args, **kwargs):
459        """Add a function, with arguments, to be called when the test is
460        completed. Functions added are called on a LIFO basis and are
461        called after tearDown on test failure or success.
462
463        Cleanup items are called even if setUp fails (unlike tearDown)."""
464        self._cleanups.append((function, args, kwargs))
465
466    def enterContext(self, cm):
467        """Enters the supplied context manager.
468
469        If successful, also adds its __exit__ method as a cleanup
470        function and returns the result of the __enter__ method.
471        """
472        return _enter_context(cm, self.addCleanup)
473
474    @classmethod
475    def addClassCleanup(cls, function, /, *args, **kwargs):
476        """Same as addCleanup, except the cleanup items are called even if
477        setUpClass fails (unlike tearDownClass)."""
478        cls._class_cleanups.append((function, args, kwargs))
479
480    @classmethod
481    def enterClassContext(cls, cm):
482        """Same as enterContext, but class-wide."""
483        return _enter_context(cm, cls.addClassCleanup)
484
485    def setUp(self):
486        "Hook method for setting up the test fixture before exercising it."
487        pass
488
489    def tearDown(self):
490        "Hook method for deconstructing the test fixture after testing it."
491        pass
492
493    @classmethod
494    def setUpClass(cls):
495        "Hook method for setting up class fixture before running tests in the class."
496
497    @classmethod
498    def tearDownClass(cls):
499        "Hook method for deconstructing the class fixture after running all tests in the class."
500
501    def countTestCases(self):
502        return 1
503
504    def defaultTestResult(self):
505        return result.TestResult()
506
507    def shortDescription(self):
508        """Returns a one-line description of the test, or None if no
509        description has been provided.
510
511        The default implementation of this method returns the first line of
512        the specified test method's docstring.
513        """
514        doc = self._testMethodDoc
515        return doc.strip().split("\n")[0].strip() if doc else None
516
517
518    def id(self):
519        return "%s.%s" % (strclass(self.__class__), self._testMethodName)
520
521    def __eq__(self, other):
522        if type(self) is not type(other):
523            return NotImplemented
524
525        return self._testMethodName == other._testMethodName
526
527    def __hash__(self):
528        return hash((type(self), self._testMethodName))
529
530    def __str__(self):
531        return "%s (%s.%s)" % (self._testMethodName, strclass(self.__class__), self._testMethodName)
532
533    def __repr__(self):
534        return "<%s testMethod=%s>" % \
535               (strclass(self.__class__), self._testMethodName)
536
537    @contextlib.contextmanager
538    def subTest(self, msg=_subtest_msg_sentinel, **params):
539        """Return a context manager that will return the enclosed block
540        of code in a subtest identified by the optional message and
541        keyword parameters.  A failure in the subtest marks the test
542        case as failed but resumes execution at the end of the enclosed
543        block, allowing further test code to be executed.
544        """
545        if self._outcome is None or not self._outcome.result_supports_subtests:
546            yield
547            return
548        parent = self._subtest
549        if parent is None:
550            params_map = _OrderedChainMap(params)
551        else:
552            params_map = parent.params.new_child(params)
553        self._subtest = _SubTest(self, msg, params_map)
554        try:
555            with self._outcome.testPartExecutor(self._subtest, subTest=True):
556                yield
557            if not self._outcome.success:
558                result = self._outcome.result
559                if result is not None and result.failfast:
560                    raise _ShouldStop
561            elif self._outcome.expectedFailure:
562                # If the test is expecting a failure, we really want to
563                # stop now and register the expected failure.
564                raise _ShouldStop
565        finally:
566            self._subtest = parent
567
568    def _addExpectedFailure(self, result, exc_info):
569        try:
570            addExpectedFailure = result.addExpectedFailure
571        except AttributeError:
572            warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
573                          RuntimeWarning)
574            result.addSuccess(self)
575        else:
576            addExpectedFailure(self, exc_info)
577
578    def _addUnexpectedSuccess(self, result):
579        try:
580            addUnexpectedSuccess = result.addUnexpectedSuccess
581        except AttributeError:
582            warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failure",
583                          RuntimeWarning)
584            # We need to pass an actual exception and traceback to addFailure,
585            # otherwise the legacy result can choke.
586            try:
587                raise _UnexpectedSuccess from None
588            except _UnexpectedSuccess:
589                result.addFailure(self, sys.exc_info())
590        else:
591            addUnexpectedSuccess(self)
592
593    def _addDuration(self, result, elapsed):
594        try:
595            addDuration = result.addDuration
596        except AttributeError:
597            warnings.warn("TestResult has no addDuration method",
598                          RuntimeWarning)
599        else:
600            addDuration(self, elapsed)
601
602    def _callSetUp(self):
603        self.setUp()
604
605    def _callTestMethod(self, method):
606        if method() is not None:
607            warnings.warn(f'It is deprecated to return a value that is not None from a '
608                          f'test case ({method})', DeprecationWarning, stacklevel=3)
609
610    def _callTearDown(self):
611        self.tearDown()
612
613    def _callCleanup(self, function, /, *args, **kwargs):
614        function(*args, **kwargs)
615
616    def run(self, result=None):
617        if result is None:
618            result = self.defaultTestResult()
619            startTestRun = getattr(result, 'startTestRun', None)
620            stopTestRun = getattr(result, 'stopTestRun', None)
621            if startTestRun is not None:
622                startTestRun()
623        else:
624            stopTestRun = None
625
626        result.startTest(self)
627        try:
628            testMethod = getattr(self, self._testMethodName)
629            if (getattr(self.__class__, "__unittest_skip__", False) or
630                getattr(testMethod, "__unittest_skip__", False)):
631                # If the class or method was skipped.
632                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
633                            or getattr(testMethod, '__unittest_skip_why__', ''))
634                _addSkip(result, self, skip_why)
635                return result
636
637            expecting_failure = (
638                getattr(self, "__unittest_expecting_failure__", False) or
639                getattr(testMethod, "__unittest_expecting_failure__", False)
640            )
641            outcome = _Outcome(result)
642            start_time = time.perf_counter()
643            try:
644                self._outcome = outcome
645
646                with outcome.testPartExecutor(self):
647                    self._callSetUp()
648                if outcome.success:
649                    outcome.expecting_failure = expecting_failure
650                    with outcome.testPartExecutor(self):
651                        self._callTestMethod(testMethod)
652                    outcome.expecting_failure = False
653                    with outcome.testPartExecutor(self):
654                        self._callTearDown()
655                self.doCleanups()
656                self._addDuration(result, (time.perf_counter() - start_time))
657
658                if outcome.success:
659                    if expecting_failure:
660                        if outcome.expectedFailure:
661                            self._addExpectedFailure(result, outcome.expectedFailure)
662                        else:
663                            self._addUnexpectedSuccess(result)
664                    else:
665                        result.addSuccess(self)
666                return result
667            finally:
668                # explicitly break reference cycle:
669                # outcome.expectedFailure -> frame -> outcome -> outcome.expectedFailure
670                outcome.expectedFailure = None
671                outcome = None
672
673                # clear the outcome, no more needed
674                self._outcome = None
675
676        finally:
677            result.stopTest(self)
678            if stopTestRun is not None:
679                stopTestRun()
680
681    def doCleanups(self):
682        """Execute all cleanup functions. Normally called for you after
683        tearDown."""
684        outcome = self._outcome or _Outcome()
685        while self._cleanups:
686            function, args, kwargs = self._cleanups.pop()
687            with outcome.testPartExecutor(self):
688                self._callCleanup(function, *args, **kwargs)
689
690        # return this for backwards compatibility
691        # even though we no longer use it internally
692        return outcome.success
693
694    @classmethod
695    def doClassCleanups(cls):
696        """Execute all class cleanup functions. Normally called for you after
697        tearDownClass."""
698        cls.tearDown_exceptions = []
699        while cls._class_cleanups:
700            function, args, kwargs = cls._class_cleanups.pop()
701            try:
702                function(*args, **kwargs)
703            except Exception:
704                cls.tearDown_exceptions.append(sys.exc_info())
705
706    def __call__(self, *args, **kwds):
707        return self.run(*args, **kwds)
708
709    def debug(self):
710        """Run the test without collecting errors in a TestResult"""
711        testMethod = getattr(self, self._testMethodName)
712        if (getattr(self.__class__, "__unittest_skip__", False) or
713            getattr(testMethod, "__unittest_skip__", False)):
714            # If the class or method was skipped.
715            skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
716                        or getattr(testMethod, '__unittest_skip_why__', ''))
717            raise SkipTest(skip_why)
718
719        self._callSetUp()
720        self._callTestMethod(testMethod)
721        self._callTearDown()
722        while self._cleanups:
723            function, args, kwargs = self._cleanups.pop()
724            self._callCleanup(function, *args, **kwargs)
725
726    def skipTest(self, reason):
727        """Skip this test."""
728        raise SkipTest(reason)
729
730    def fail(self, msg=None):
731        """Fail immediately, with the given message."""
732        raise self.failureException(msg)
733
734    def assertFalse(self, expr, msg=None):
735        """Check that the expression is false."""
736        if expr:
737            msg = self._formatMessage(msg, "%s is not false" % safe_repr(expr))
738            raise self.failureException(msg)
739
740    def assertTrue(self, expr, msg=None):
741        """Check that the expression is true."""
742        if not expr:
743            msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
744            raise self.failureException(msg)
745
746    def _formatMessage(self, msg, standardMsg):
747        """Honour the longMessage attribute when generating failure messages.
748        If longMessage is False this means:
749        * Use only an explicit message if it is provided
750        * Otherwise use the standard message for the assert
751
752        If longMessage is True:
753        * Use the standard message
754        * If an explicit message is provided, plus ' : ' and the explicit message
755        """
756        if not self.longMessage:
757            return msg or standardMsg
758        if msg is None:
759            return standardMsg
760        try:
761            # don't switch to '{}' formatting in Python 2.X
762            # it changes the way unicode input is handled
763            return '%s : %s' % (standardMsg, msg)
764        except UnicodeDecodeError:
765            return  '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
766
767    def assertRaises(self, expected_exception, *args, **kwargs):
768        """Fail unless an exception of class expected_exception is raised
769           by the callable when invoked with specified positional and
770           keyword arguments. If a different type of exception is
771           raised, it will not be caught, and the test case will be
772           deemed to have suffered an error, exactly as for an
773           unexpected exception.
774
775           If called with the callable and arguments omitted, will return a
776           context object used like this::
777
778                with self.assertRaises(SomeException):
779                    do_something()
780
781           An optional keyword argument 'msg' can be provided when assertRaises
782           is used as a context object.
783
784           The context manager keeps a reference to the exception as
785           the 'exception' attribute. This allows you to inspect the
786           exception after the assertion::
787
788               with self.assertRaises(SomeException) as cm:
789                   do_something()
790               the_exception = cm.exception
791               self.assertEqual(the_exception.error_code, 3)
792        """
793        context = _AssertRaisesContext(expected_exception, self)
794        try:
795            return context.handle('assertRaises', args, kwargs)
796        finally:
797            # bpo-23890: manually break a reference cycle
798            context = None
799
800    def assertWarns(self, expected_warning, *args, **kwargs):
801        """Fail unless a warning of class warnClass is triggered
802           by the callable when invoked with specified positional and
803           keyword arguments.  If a different type of warning is
804           triggered, it will not be handled: depending on the other
805           warning filtering rules in effect, it might be silenced, printed
806           out, or raised as an exception.
807
808           If called with the callable and arguments omitted, will return a
809           context object used like this::
810
811                with self.assertWarns(SomeWarning):
812                    do_something()
813
814           An optional keyword argument 'msg' can be provided when assertWarns
815           is used as a context object.
816
817           The context manager keeps a reference to the first matching
818           warning as the 'warning' attribute; similarly, the 'filename'
819           and 'lineno' attributes give you information about the line
820           of Python code from which the warning was triggered.
821           This allows you to inspect the warning after the assertion::
822
823               with self.assertWarns(SomeWarning) as cm:
824                   do_something()
825               the_warning = cm.warning
826               self.assertEqual(the_warning.some_attribute, 147)
827        """
828        context = _AssertWarnsContext(expected_warning, self)
829        return context.handle('assertWarns', args, kwargs)
830
831    def _assertNotWarns(self, expected_warning, *args, **kwargs):
832        """The opposite of assertWarns. Private due to low demand."""
833        context = _AssertNotWarnsContext(expected_warning, self)
834        return context.handle('_assertNotWarns', args, kwargs)
835
836    def assertLogs(self, logger=None, level=None):
837        """Fail unless a log message of level *level* or higher is emitted
838        on *logger_name* or its children.  If omitted, *level* defaults to
839        INFO and *logger* defaults to the root logger.
840
841        This method must be used as a context manager, and will yield
842        a recording object with two attributes: `output` and `records`.
843        At the end of the context manager, the `output` attribute will
844        be a list of the matching formatted log messages and the
845        `records` attribute will be a list of the corresponding LogRecord
846        objects.
847
848        Example::
849
850            with self.assertLogs('foo', level='INFO') as cm:
851                logging.getLogger('foo').info('first message')
852                logging.getLogger('foo.bar').error('second message')
853            self.assertEqual(cm.output, ['INFO:foo:first message',
854                                         'ERROR:foo.bar:second message'])
855        """
856        # Lazy import to avoid importing logging if it is not needed.
857        from ._log import _AssertLogsContext
858        return _AssertLogsContext(self, logger, level, no_logs=False)
859
860    def assertNoLogs(self, logger=None, level=None):
861        """ Fail unless no log messages of level *level* or higher are emitted
862        on *logger_name* or its children.
863
864        This method must be used as a context manager.
865        """
866        from ._log import _AssertLogsContext
867        return _AssertLogsContext(self, logger, level, no_logs=True)
868
869    def _getAssertEqualityFunc(self, first, second):
870        """Get a detailed comparison function for the types of the two args.
871
872        Returns: A callable accepting (first, second, msg=None) that will
873        raise a failure exception if first != second with a useful human
874        readable error message for those types.
875        """
876        #
877        # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
878        # and vice versa.  I opted for the conservative approach in case
879        # subclasses are not intended to be compared in detail to their super
880        # class instances using a type equality func.  This means testing
881        # subtypes won't automagically use the detailed comparison.  Callers
882        # should use their type specific assertSpamEqual method to compare
883        # subclasses if the detailed comparison is desired and appropriate.
884        # See the discussion in http://bugs.python.org/issue2578.
885        #
886        if type(first) is type(second):
887            asserter = self._type_equality_funcs.get(type(first))
888            if asserter is not None:
889                if isinstance(asserter, str):
890                    asserter = getattr(self, asserter)
891                return asserter
892
893        return self._baseAssertEqual
894
895    def _baseAssertEqual(self, first, second, msg=None):
896        """The default assertEqual implementation, not type specific."""
897        if not first == second:
898            standardMsg = '%s != %s' % _common_shorten_repr(first, second)
899            msg = self._formatMessage(msg, standardMsg)
900            raise self.failureException(msg)
901
902    def assertEqual(self, first, second, msg=None):
903        """Fail if the two objects are unequal as determined by the '=='
904           operator.
905        """
906        assertion_func = self._getAssertEqualityFunc(first, second)
907        assertion_func(first, second, msg=msg)
908
909    def assertNotEqual(self, first, second, msg=None):
910        """Fail if the two objects are equal as determined by the '!='
911           operator.
912        """
913        if not first != second:
914            msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
915                                                          safe_repr(second)))
916            raise self.failureException(msg)
917
918    def assertAlmostEqual(self, first, second, places=None, msg=None,
919                          delta=None):
920        """Fail if the two objects are unequal as determined by their
921           difference rounded to the given number of decimal places
922           (default 7) and comparing to zero, or by comparing that the
923           difference between the two objects is more than the given
924           delta.
925
926           Note that decimal places (from zero) are usually not the same
927           as significant digits (measured from the most significant digit).
928
929           If the two objects compare equal then they will automatically
930           compare almost equal.
931        """
932        if first == second:
933            # shortcut
934            return
935        if delta is not None and places is not None:
936            raise TypeError("specify delta or places not both")
937
938        diff = abs(first - second)
939        if delta is not None:
940            if diff <= delta:
941                return
942
943            standardMsg = '%s != %s within %s delta (%s difference)' % (
944                safe_repr(first),
945                safe_repr(second),
946                safe_repr(delta),
947                safe_repr(diff))
948        else:
949            if places is None:
950                places = 7
951
952            if round(diff, places) == 0:
953                return
954
955            standardMsg = '%s != %s within %r places (%s difference)' % (
956                safe_repr(first),
957                safe_repr(second),
958                places,
959                safe_repr(diff))
960        msg = self._formatMessage(msg, standardMsg)
961        raise self.failureException(msg)
962
963    def assertNotAlmostEqual(self, first, second, places=None, msg=None,
964                             delta=None):
965        """Fail if the two objects are equal as determined by their
966           difference rounded to the given number of decimal places
967           (default 7) and comparing to zero, or by comparing that the
968           difference between the two objects is less than the given delta.
969
970           Note that decimal places (from zero) are usually not the same
971           as significant digits (measured from the most significant digit).
972
973           Objects that are equal automatically fail.
974        """
975        if delta is not None and places is not None:
976            raise TypeError("specify delta or places not both")
977        diff = abs(first - second)
978        if delta is not None:
979            if not (first == second) and diff > delta:
980                return
981            standardMsg = '%s == %s within %s delta (%s difference)' % (
982                safe_repr(first),
983                safe_repr(second),
984                safe_repr(delta),
985                safe_repr(diff))
986        else:
987            if places is None:
988                places = 7
989            if not (first == second) and round(diff, places) != 0:
990                return
991            standardMsg = '%s == %s within %r places' % (safe_repr(first),
992                                                         safe_repr(second),
993                                                         places)
994
995        msg = self._formatMessage(msg, standardMsg)
996        raise self.failureException(msg)
997
998    def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
999        """An equality assertion for ordered sequences (like lists and tuples).
1000
1001        For the purposes of this function, a valid ordered sequence type is one
1002        which can be indexed, has a length, and has an equality operator.
1003
1004        Args:
1005            seq1: The first sequence to compare.
1006            seq2: The second sequence to compare.
1007            seq_type: The expected datatype of the sequences, or None if no
1008                    datatype should be enforced.
1009            msg: Optional message to use on failure instead of a list of
1010                    differences.
1011        """
1012        if seq_type is not None:
1013            seq_type_name = seq_type.__name__
1014            if not isinstance(seq1, seq_type):
1015                raise self.failureException('First sequence is not a %s: %s'
1016                                        % (seq_type_name, safe_repr(seq1)))
1017            if not isinstance(seq2, seq_type):
1018                raise self.failureException('Second sequence is not a %s: %s'
1019                                        % (seq_type_name, safe_repr(seq2)))
1020        else:
1021            seq_type_name = "sequence"
1022
1023        differing = None
1024        try:
1025            len1 = len(seq1)
1026        except (TypeError, NotImplementedError):
1027            differing = 'First %s has no length.    Non-sequence?' % (
1028                    seq_type_name)
1029
1030        if differing is None:
1031            try:
1032                len2 = len(seq2)
1033            except (TypeError, NotImplementedError):
1034                differing = 'Second %s has no length.    Non-sequence?' % (
1035                        seq_type_name)
1036
1037        if differing is None:
1038            if seq1 == seq2:
1039                return
1040
1041            differing = '%ss differ: %s != %s\n' % (
1042                    (seq_type_name.capitalize(),) +
1043                    _common_shorten_repr(seq1, seq2))
1044
1045            for i in range(min(len1, len2)):
1046                try:
1047                    item1 = seq1[i]
1048                except (TypeError, IndexError, NotImplementedError):
1049                    differing += ('\nUnable to index element %d of first %s\n' %
1050                                 (i, seq_type_name))
1051                    break
1052
1053                try:
1054                    item2 = seq2[i]
1055                except (TypeError, IndexError, NotImplementedError):
1056                    differing += ('\nUnable to index element %d of second %s\n' %
1057                                 (i, seq_type_name))
1058                    break
1059
1060                if item1 != item2:
1061                    differing += ('\nFirst differing element %d:\n%s\n%s\n' %
1062                                 ((i,) + _common_shorten_repr(item1, item2)))
1063                    break
1064            else:
1065                if (len1 == len2 and seq_type is None and
1066                    type(seq1) != type(seq2)):
1067                    # The sequences are the same, but have differing types.
1068                    return
1069
1070            if len1 > len2:
1071                differing += ('\nFirst %s contains %d additional '
1072                             'elements.\n' % (seq_type_name, len1 - len2))
1073                try:
1074                    differing += ('First extra element %d:\n%s\n' %
1075                                  (len2, safe_repr(seq1[len2])))
1076                except (TypeError, IndexError, NotImplementedError):
1077                    differing += ('Unable to index element %d '
1078                                  'of first %s\n' % (len2, seq_type_name))
1079            elif len1 < len2:
1080                differing += ('\nSecond %s contains %d additional '
1081                             'elements.\n' % (seq_type_name, len2 - len1))
1082                try:
1083                    differing += ('First extra element %d:\n%s\n' %
1084                                  (len1, safe_repr(seq2[len1])))
1085                except (TypeError, IndexError, NotImplementedError):
1086                    differing += ('Unable to index element %d '
1087                                  'of second %s\n' % (len1, seq_type_name))
1088        standardMsg = differing
1089        diffMsg = '\n' + '\n'.join(
1090            difflib.ndiff(pprint.pformat(seq1).splitlines(),
1091                          pprint.pformat(seq2).splitlines()))
1092
1093        standardMsg = self._truncateMessage(standardMsg, diffMsg)
1094        msg = self._formatMessage(msg, standardMsg)
1095        self.fail(msg)
1096
1097    def _truncateMessage(self, message, diff):
1098        max_diff = self.maxDiff
1099        if max_diff is None or len(diff) <= max_diff:
1100            return message + diff
1101        return message + (DIFF_OMITTED % len(diff))
1102
1103    def assertListEqual(self, list1, list2, msg=None):
1104        """A list-specific equality assertion.
1105
1106        Args:
1107            list1: The first list to compare.
1108            list2: The second list to compare.
1109            msg: Optional message to use on failure instead of a list of
1110                    differences.
1111
1112        """
1113        self.assertSequenceEqual(list1, list2, msg, seq_type=list)
1114
1115    def assertTupleEqual(self, tuple1, tuple2, msg=None):
1116        """A tuple-specific equality assertion.
1117
1118        Args:
1119            tuple1: The first tuple to compare.
1120            tuple2: The second tuple to compare.
1121            msg: Optional message to use on failure instead of a list of
1122                    differences.
1123        """
1124        self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
1125
1126    def assertSetEqual(self, set1, set2, msg=None):
1127        """A set-specific equality assertion.
1128
1129        Args:
1130            set1: The first set to compare.
1131            set2: The second set to compare.
1132            msg: Optional message to use on failure instead of a list of
1133                    differences.
1134
1135        assertSetEqual uses ducktyping to support different types of sets, and
1136        is optimized for sets specifically (parameters must support a
1137        difference method).
1138        """
1139        try:
1140            difference1 = set1.difference(set2)
1141        except TypeError as e:
1142            self.fail('invalid type when attempting set difference: %s' % e)
1143        except AttributeError as e:
1144            self.fail('first argument does not support set difference: %s' % e)
1145
1146        try:
1147            difference2 = set2.difference(set1)
1148        except TypeError as e:
1149            self.fail('invalid type when attempting set difference: %s' % e)
1150        except AttributeError as e:
1151            self.fail('second argument does not support set difference: %s' % e)
1152
1153        if not (difference1 or difference2):
1154            return
1155
1156        lines = []
1157        if difference1:
1158            lines.append('Items in the first set but not the second:')
1159            for item in difference1:
1160                lines.append(repr(item))
1161        if difference2:
1162            lines.append('Items in the second set but not the first:')
1163            for item in difference2:
1164                lines.append(repr(item))
1165
1166        standardMsg = '\n'.join(lines)
1167        self.fail(self._formatMessage(msg, standardMsg))
1168
1169    def assertIn(self, member, container, msg=None):
1170        """Just like self.assertTrue(a in b), but with a nicer default message."""
1171        if member not in container:
1172            standardMsg = '%s not found in %s' % (safe_repr(member),
1173                                                  safe_repr(container))
1174            self.fail(self._formatMessage(msg, standardMsg))
1175
1176    def assertNotIn(self, member, container, msg=None):
1177        """Just like self.assertTrue(a not in b), but with a nicer default message."""
1178        if member in container:
1179            standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
1180                                                        safe_repr(container))
1181            self.fail(self._formatMessage(msg, standardMsg))
1182
1183    def assertIs(self, expr1, expr2, msg=None):
1184        """Just like self.assertTrue(a is b), but with a nicer default message."""
1185        if expr1 is not expr2:
1186            standardMsg = '%s is not %s' % (safe_repr(expr1),
1187                                             safe_repr(expr2))
1188            self.fail(self._formatMessage(msg, standardMsg))
1189
1190    def assertIsNot(self, expr1, expr2, msg=None):
1191        """Just like self.assertTrue(a is not b), but with a nicer default message."""
1192        if expr1 is expr2:
1193            standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
1194            self.fail(self._formatMessage(msg, standardMsg))
1195
1196    def assertDictEqual(self, d1, d2, msg=None):
1197        self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
1198        self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')
1199
1200        if d1 != d2:
1201            standardMsg = '%s != %s' % _common_shorten_repr(d1, d2)
1202            diff = ('\n' + '\n'.join(difflib.ndiff(
1203                           pprint.pformat(d1).splitlines(),
1204                           pprint.pformat(d2).splitlines())))
1205            standardMsg = self._truncateMessage(standardMsg, diff)
1206            self.fail(self._formatMessage(msg, standardMsg))
1207
1208    def assertCountEqual(self, first, second, msg=None):
1209        """Asserts that two iterables have the same elements, the same number of
1210        times, without regard to order.
1211
1212            self.assertEqual(Counter(list(first)),
1213                             Counter(list(second)))
1214
1215         Example:
1216            - [0, 1, 1] and [1, 0, 1] compare equal.
1217            - [0, 0, 1] and [0, 1] compare unequal.
1218
1219        """
1220        first_seq, second_seq = list(first), list(second)
1221        try:
1222            first = collections.Counter(first_seq)
1223            second = collections.Counter(second_seq)
1224        except TypeError:
1225            # Handle case with unhashable elements
1226            differences = _count_diff_all_purpose(first_seq, second_seq)
1227        else:
1228            if first == second:
1229                return
1230            differences = _count_diff_hashable(first_seq, second_seq)
1231
1232        if differences:
1233            standardMsg = 'Element counts were not equal:\n'
1234            lines = ['First has %d, Second has %d:  %r' % diff for diff in differences]
1235            diffMsg = '\n'.join(lines)
1236            standardMsg = self._truncateMessage(standardMsg, diffMsg)
1237            msg = self._formatMessage(msg, standardMsg)
1238            self.fail(msg)
1239
1240    def assertMultiLineEqual(self, first, second, msg=None):
1241        """Assert that two multi-line strings are equal."""
1242        self.assertIsInstance(first, str, "First argument is not a string")
1243        self.assertIsInstance(second, str, "Second argument is not a string")
1244
1245        if first != second:
1246            # Don't use difflib if the strings are too long
1247            if (len(first) > self._diffThreshold or
1248                len(second) > self._diffThreshold):
1249                self._baseAssertEqual(first, second, msg)
1250
1251            # Append \n to both strings if either is missing the \n.
1252            # This allows the final ndiff to show the \n difference. The
1253            # exception here is if the string is empty, in which case no
1254            # \n should be added
1255            first_presplit = first
1256            second_presplit = second
1257            if first and second:
1258                if first[-1] != '\n' or second[-1] != '\n':
1259                    first_presplit += '\n'
1260                    second_presplit += '\n'
1261            elif second and second[-1] != '\n':
1262                second_presplit += '\n'
1263            elif first and first[-1] != '\n':
1264                first_presplit += '\n'
1265
1266            firstlines = first_presplit.splitlines(keepends=True)
1267            secondlines = second_presplit.splitlines(keepends=True)
1268
1269            # Generate the message and diff, then raise the exception
1270            standardMsg = '%s != %s' % _common_shorten_repr(first, second)
1271            diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines))
1272            standardMsg = self._truncateMessage(standardMsg, diff)
1273            self.fail(self._formatMessage(msg, standardMsg))
1274
1275    def assertLess(self, a, b, msg=None):
1276        """Just like self.assertTrue(a < b), but with a nicer default message."""
1277        if not a < b:
1278            standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
1279            self.fail(self._formatMessage(msg, standardMsg))
1280
1281    def assertLessEqual(self, a, b, msg=None):
1282        """Just like self.assertTrue(a <= b), but with a nicer default message."""
1283        if not a <= b:
1284            standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
1285            self.fail(self._formatMessage(msg, standardMsg))
1286
1287    def assertGreater(self, a, b, msg=None):
1288        """Just like self.assertTrue(a > b), but with a nicer default message."""
1289        if not a > b:
1290            standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
1291            self.fail(self._formatMessage(msg, standardMsg))
1292
1293    def assertGreaterEqual(self, a, b, msg=None):
1294        """Just like self.assertTrue(a >= b), but with a nicer default message."""
1295        if not a >= b:
1296            standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
1297            self.fail(self._formatMessage(msg, standardMsg))
1298
1299    def assertIsNone(self, obj, msg=None):
1300        """Same as self.assertTrue(obj is None), with a nicer default message."""
1301        if obj is not None:
1302            standardMsg = '%s is not None' % (safe_repr(obj),)
1303            self.fail(self._formatMessage(msg, standardMsg))
1304
1305    def assertIsNotNone(self, obj, msg=None):
1306        """Included for symmetry with assertIsNone."""
1307        if obj is None:
1308            standardMsg = 'unexpectedly None'
1309            self.fail(self._formatMessage(msg, standardMsg))
1310
1311    def assertIsInstance(self, obj, cls, msg=None):
1312        """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
1313        default message."""
1314        if not isinstance(obj, cls):
1315            standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
1316            self.fail(self._formatMessage(msg, standardMsg))
1317
1318    def assertNotIsInstance(self, obj, cls, msg=None):
1319        """Included for symmetry with assertIsInstance."""
1320        if isinstance(obj, cls):
1321            standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
1322            self.fail(self._formatMessage(msg, standardMsg))
1323
1324    def assertRaisesRegex(self, expected_exception, expected_regex,
1325                          *args, **kwargs):
1326        """Asserts that the message in a raised exception matches a regex.
1327
1328        Args:
1329            expected_exception: Exception class expected to be raised.
1330            expected_regex: Regex (re.Pattern object or string) expected
1331                    to be found in error message.
1332            args: Function to be called and extra positional args.
1333            kwargs: Extra kwargs.
1334            msg: Optional message used in case of failure. Can only be used
1335                    when assertRaisesRegex is used as a context manager.
1336        """
1337        context = _AssertRaisesContext(expected_exception, self, expected_regex)
1338        return context.handle('assertRaisesRegex', args, kwargs)
1339
1340    def assertWarnsRegex(self, expected_warning, expected_regex,
1341                         *args, **kwargs):
1342        """Asserts that the message in a triggered warning matches a regexp.
1343        Basic functioning is similar to assertWarns() with the addition
1344        that only warnings whose messages also match the regular expression
1345        are considered successful matches.
1346
1347        Args:
1348            expected_warning: Warning class expected to be triggered.
1349            expected_regex: Regex (re.Pattern object or string) expected
1350                    to be found in error message.
1351            args: Function to be called and extra positional args.
1352            kwargs: Extra kwargs.
1353            msg: Optional message used in case of failure. Can only be used
1354                    when assertWarnsRegex is used as a context manager.
1355        """
1356        context = _AssertWarnsContext(expected_warning, self, expected_regex)
1357        return context.handle('assertWarnsRegex', args, kwargs)
1358
1359    def assertRegex(self, text, expected_regex, msg=None):
1360        """Fail the test unless the text matches the regular expression."""
1361        if isinstance(expected_regex, (str, bytes)):
1362            assert expected_regex, "expected_regex must not be empty."
1363            expected_regex = re.compile(expected_regex)
1364        if not expected_regex.search(text):
1365            standardMsg = "Regex didn't match: %r not found in %r" % (
1366                expected_regex.pattern, text)
1367            # _formatMessage ensures the longMessage option is respected
1368            msg = self._formatMessage(msg, standardMsg)
1369            raise self.failureException(msg)
1370
1371    def assertNotRegex(self, text, unexpected_regex, msg=None):
1372        """Fail the test if the text matches the regular expression."""
1373        if isinstance(unexpected_regex, (str, bytes)):
1374            unexpected_regex = re.compile(unexpected_regex)
1375        match = unexpected_regex.search(text)
1376        if match:
1377            standardMsg = 'Regex matched: %r matches %r in %r' % (
1378                text[match.start() : match.end()],
1379                unexpected_regex.pattern,
1380                text)
1381            # _formatMessage ensures the longMessage option is respected
1382            msg = self._formatMessage(msg, standardMsg)
1383            raise self.failureException(msg)
1384
1385
1386
1387class FunctionTestCase(TestCase):
1388    """A test case that wraps a test function.
1389
1390    This is useful for slipping pre-existing test functions into the
1391    unittest framework. Optionally, set-up and tidy-up functions can be
1392    supplied. As with TestCase, the tidy-up ('tearDown') function will
1393    always be called if the set-up ('setUp') function ran successfully.
1394    """
1395
1396    def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
1397        super(FunctionTestCase, self).__init__()
1398        self._setUpFunc = setUp
1399        self._tearDownFunc = tearDown
1400        self._testFunc = testFunc
1401        self._description = description
1402
1403    def setUp(self):
1404        if self._setUpFunc is not None:
1405            self._setUpFunc()
1406
1407    def tearDown(self):
1408        if self._tearDownFunc is not None:
1409            self._tearDownFunc()
1410
1411    def runTest(self):
1412        self._testFunc()
1413
1414    def id(self):
1415        return self._testFunc.__name__
1416
1417    def __eq__(self, other):
1418        if not isinstance(other, self.__class__):
1419            return NotImplemented
1420
1421        return self._setUpFunc == other._setUpFunc and \
1422               self._tearDownFunc == other._tearDownFunc and \
1423               self._testFunc == other._testFunc and \
1424               self._description == other._description
1425
1426    def __hash__(self):
1427        return hash((type(self), self._setUpFunc, self._tearDownFunc,
1428                     self._testFunc, self._description))
1429
1430    def __str__(self):
1431        return "%s (%s)" % (strclass(self.__class__),
1432                            self._testFunc.__name__)
1433
1434    def __repr__(self):
1435        return "<%s tec=%s>" % (strclass(self.__class__),
1436                                     self._testFunc)
1437
1438    def shortDescription(self):
1439        if self._description is not None:
1440            return self._description
1441        doc = self._testFunc.__doc__
1442        return doc and doc.split("\n")[0].strip() or None
1443
1444
1445class _SubTest(TestCase):
1446
1447    def __init__(self, test_case, message, params):
1448        super().__init__()
1449        self._message = message
1450        self.test_case = test_case
1451        self.params = params
1452        self.failureException = test_case.failureException
1453
1454    def runTest(self):
1455        raise NotImplementedError("subtests cannot be run directly")
1456
1457    def _subDescription(self):
1458        parts = []
1459        if self._message is not _subtest_msg_sentinel:
1460            parts.append("[{}]".format(self._message))
1461        if self.params:
1462            params_desc = ', '.join(
1463                "{}={!r}".format(k, v)
1464                for (k, v) in self.params.items())
1465            parts.append("({})".format(params_desc))
1466        return " ".join(parts) or '(<subtest>)'
1467
1468    def id(self):
1469        return "{} {}".format(self.test_case.id(), self._subDescription())
1470
1471    def shortDescription(self):
1472        """Returns a one-line description of the subtest, or None if no
1473        description has been provided.
1474        """
1475        return self.test_case.shortDescription()
1476
1477    def __str__(self):
1478        return "{} {}".format(self.test_case, self._subDescription())
1479