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