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