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