github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/third_party/stdlib/unittest_case.py (about) 1 """Test case implementation""" 2 3 import collections 4 import sys 5 import functools 6 import difflib 7 import pprint 8 import re 9 import types 10 import warnings 11 12 # from . import result 13 import unittest_result as result 14 import unittest_util as _util 15 # from .util import ( 16 # strclass, safe_repr, unorderable_list_difference, 17 # _count_diff_all_purpose, _count_diff_hashable 18 # ) 19 strclass, safe_repr, unorderable_list_difference, _count_diff_all_purpose, \ 20 _count_diff_hashable = _util.strclass, _util.safe_repr, \ 21 _util.unorderable_list_difference, _util._count_diff_all_purpose, \ 22 _util._count_diff_hashable 23 24 class KeyboardInterrupt(BaseException): 25 pass 26 27 28 __unittest = True 29 30 31 DIFF_OMITTED = ('\nDiff is %s characters long. ' 32 'Set self.maxDiff to None to see it.') 33 34 class SkipTest(Exception): 35 """ 36 Raise this exception in a test to skip it. 37 38 Usually you can use TestCase.skipTest() or one of the skipping decorators 39 instead of raising this directly. 40 """ 41 pass 42 43 class _ExpectedFailure(Exception): 44 """ 45 Raise this when a test is expected to fail. 46 47 This is an implementation detail. 48 """ 49 50 def __init__(self, exc_info): 51 super(_ExpectedFailure, self).__init__() 52 self.exc_info = exc_info 53 54 class _UnexpectedSuccess(Exception): 55 """ 56 The test was supposed to fail, but it didn't! 57 """ 58 pass 59 60 def _id(obj): 61 return obj 62 63 def skip(reason): 64 """ 65 Unconditionally skip a test. 66 """ 67 def decorator(test_item): 68 if not isinstance(test_item, (type, types.ClassType)): 69 # @functools.wraps(test_item) 70 def skip_wrapper(*args, **kwargs): 71 raise SkipTest(reason) 72 skip_wrapper = functools.wraps(test_item)(skip_wrapper) 73 test_item = skip_wrapper 74 75 test_item.__unittest_skip__ = True 76 test_item.__unittest_skip_why__ = reason 77 return test_item 78 return decorator 79 80 def skipIf(condition, reason): 81 """ 82 Skip a test if the condition is true. 83 """ 84 if condition: 85 return skip(reason) 86 return _id 87 88 def skipUnless(condition, reason): 89 """ 90 Skip a test unless the condition is true. 91 """ 92 if not condition: 93 return skip(reason) 94 return _id 95 96 97 def expectedFailure(func): 98 # @functools.wraps(func) 99 def wrapper(*args, **kwargs): 100 try: 101 func(*args, **kwargs) 102 except Exception: 103 raise _ExpectedFailure(sys.exc_info()) 104 raise _UnexpectedSuccess 105 wrapper = functools.wraps(func)(wrapper) 106 return wrapper 107 108 109 class _AssertRaisesContext(object): 110 """A context manager used to implement TestCase.assertRaises* methods.""" 111 112 def __init__(self, expected, test_case, expected_regexp=None): 113 self.expected = expected 114 self.failureException = test_case.failureException 115 self.expected_regexp = expected_regexp 116 117 def __enter__(self): 118 return self 119 120 def __exit__(self, exc_type, exc_value, tb): 121 if exc_type is None: 122 try: 123 exc_name = self.expected.__name__ 124 except AttributeError: 125 exc_name = str(self.expected) 126 raise self.failureException( 127 # "{0} not raised".format(exc_name)) 128 "%s not raised" % (exc_name)) 129 if not issubclass(exc_type, self.expected): 130 # let unexpected exceptions pass through 131 return False 132 self.exception = exc_value # store for later retrieval 133 if self.expected_regexp is None: 134 return True 135 136 expected_regexp = self.expected_regexp 137 if not expected_regexp.search(str(exc_value)): 138 raise self.failureException('"%s" does not match "%s"' % 139 (expected_regexp.pattern, str(exc_value))) 140 return True 141 142 143 class TestCase(object): 144 """A class whose instances are single test cases. 145 146 By default, the test code itself should be placed in a method named 147 'runTest'. 148 149 If the fixture may be used for many test cases, create as 150 many test methods as are needed. When instantiating such a TestCase 151 subclass, specify in the constructor arguments the name of the test method 152 that the instance is to execute. 153 154 Test authors should subclass TestCase for their own tests. Construction 155 and deconstruction of the test's environment ('fixture') can be 156 implemented by overriding the 'setUp' and 'tearDown' methods respectively. 157 158 If it is necessary to override the __init__ method, the base class 159 __init__ method must always be called. It is important that subclasses 160 should not change the signature of their __init__ method, since instances 161 of the classes are instantiated automatically by parts of the framework 162 in order to be run. 163 164 When subclassing TestCase, you can set these attributes: 165 * failureException: determines which exception will be raised when 166 the instance's assertion methods fail; test methods raising this 167 exception will be deemed to have 'failed' rather than 'errored'. 168 * longMessage: determines whether long messages (including repr of 169 objects used in assert methods) will be printed on failure in *addition* 170 to any explicit message passed. 171 * maxDiff: sets the maximum length of a diff in failure messages 172 by assert methods using difflib. It is looked up as an instance 173 attribute so can be configured by individual tests if required. 174 """ 175 176 failureException = AssertionError 177 178 longMessage = False 179 180 maxDiff = 80*8 181 182 # If a string is longer than _diffThreshold, use normal comparison instead 183 # of difflib. See #11763. 184 # _diffThreshold = 2**16 185 _diffThreshold = 1<<16 186 187 # Attribute used by TestSuite for classSetUp 188 189 _classSetupFailed = False 190 191 def __init__(self, methodName='runTest'): 192 """Create an instance of the class that will use the named test 193 method when executed. Raises a ValueError if the instance does 194 not have a method with the specified name. 195 """ 196 self._testMethodName = methodName 197 self._resultForDoCleanups = None 198 try: 199 testMethod = getattr(self, methodName) 200 except AttributeError: 201 raise ValueError("no such test method in %s: %s" % 202 (self.__class__, methodName)) 203 # self._testMethodDoc = testMethod.__doc__ 204 self._cleanups = [] 205 206 # Map types to custom assertEqual functions that will compare 207 # instances of said type in more detail to generate a more useful 208 # error message. 209 self._type_equality_funcs = {} 210 self.addTypeEqualityFunc(dict, 'assertDictEqual') 211 self.addTypeEqualityFunc(list, 'assertListEqual') 212 self.addTypeEqualityFunc(tuple, 'assertTupleEqual') 213 self.addTypeEqualityFunc(set, 'assertSetEqual') 214 self.addTypeEqualityFunc(frozenset, 'assertSetEqual') 215 try: 216 self.addTypeEqualityFunc(unicode, 'assertMultiLineEqual') 217 except NameError: 218 # No unicode support in this build 219 pass 220 221 def addTypeEqualityFunc(self, typeobj, function): 222 """Add a type specific assertEqual style function to compare a type. 223 224 This method is for use by TestCase subclasses that need to register 225 their own type equality functions to provide nicer error messages. 226 227 Args: 228 typeobj: The data type to call this function on when both values 229 are of the same type in assertEqual(). 230 function: The callable taking two arguments and an optional 231 msg= argument that raises self.failureException with a 232 useful error message when the two arguments are not equal. 233 """ 234 self._type_equality_funcs[typeobj] = function 235 236 def addCleanup(self, function, *args, **kwargs): 237 """Add a function, with arguments, to be called when the test is 238 completed. Functions added are called on a LIFO basis and are 239 called after tearDown on test failure or success. 240 241 Cleanup items are called even if setUp fails (unlike tearDown).""" 242 self._cleanups.append((function, args, kwargs)) 243 244 def setUp(self): 245 "Hook method for setting up the test fixture before exercising it." 246 pass 247 248 def tearDown(self): 249 "Hook method for deconstructing the test fixture after testing it." 250 pass 251 252 # @classmethod 253 def setUpClass(cls): 254 "Hook method for setting up class fixture before running tests in the class." 255 setUpClass = classmethod(setUpClass) 256 257 # @classmethod 258 def tearDownClass(cls): 259 "Hook method for deconstructing the class fixture after running all tests in the class." 260 tearDownClass = classmethod(tearDownClass) 261 262 def countTestCases(self): 263 return 1 264 265 def defaultTestResult(self): 266 return result.TestResult() 267 268 def shortDescription(self): 269 """Returns a one-line description of the test, or None if no 270 description has been provided. 271 272 The default implementation of this method returns the first line of 273 the specified test method's docstring. 274 """ 275 # doc = self._testMethodDoc 276 # return doc and doc.split("\n")[0].strip() or None 277 return '' 278 279 280 def id(self): 281 return "%s.%s" % (strclass(self.__class__), self._testMethodName) 282 283 def __eq__(self, other): 284 if type(self) is not type(other): 285 return NotImplemented 286 287 return self._testMethodName == other._testMethodName 288 289 def __ne__(self, other): 290 return not self == other 291 292 def __hash__(self): 293 return hash((type(self), self._testMethodName)) 294 295 def __str__(self): 296 return "%s (%s)" % (self._testMethodName, strclass(self.__class__)) 297 298 def __repr__(self): 299 return "<%s testMethod=%s>" % \ 300 (strclass(self.__class__), self._testMethodName) 301 302 def _addSkip(self, result, reason): 303 addSkip = getattr(result, 'addSkip', None) 304 if addSkip is not None: 305 addSkip(self, reason) 306 else: 307 warnings.warn("TestResult has no addSkip method, skips not reported", 308 RuntimeWarning, 2) 309 result.addSuccess(self) 310 311 def run(self, result=None): 312 orig_result = result 313 if result is None: 314 result = self.defaultTestResult() 315 startTestRun = getattr(result, 'startTestRun', None) 316 if startTestRun is not None: 317 startTestRun() 318 319 self._resultForDoCleanups = result 320 result.startTest(self) 321 322 testMethod = getattr(self, self._testMethodName) 323 if (getattr(self.__class__, "__unittest_skip__", False) or 324 getattr(testMethod, "__unittest_skip__", False)): 325 # If the class or method was skipped. 326 try: 327 skip_why = (getattr(self.__class__, '__unittest_skip_why__', '') 328 or getattr(testMethod, '__unittest_skip_why__', '')) 329 self._addSkip(result, skip_why) 330 finally: 331 result.stopTest(self) 332 return 333 try: 334 success = False 335 try: 336 self.setUp() 337 except SkipTest as e: 338 self._addSkip(result, str(e)) 339 except KeyboardInterrupt: 340 raise 341 except: 342 result.addError(self, sys.exc_info()) 343 else: 344 try: 345 testMethod() 346 except KeyboardInterrupt: 347 raise 348 except self.failureException: 349 result.addFailure(self, sys.exc_info()) 350 except _ExpectedFailure as e: 351 addExpectedFailure = getattr(result, 'addExpectedFailure', None) 352 if addExpectedFailure is not None: 353 addExpectedFailure(self, e.exc_info) 354 else: 355 warnings.warn("TestResult has no addExpectedFailure method, reporting as passes", 356 RuntimeWarning) 357 result.addSuccess(self) 358 except _UnexpectedSuccess: 359 addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None) 360 if addUnexpectedSuccess is not None: 361 addUnexpectedSuccess(self) 362 else: 363 warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures", 364 RuntimeWarning) 365 result.addFailure(self, sys.exc_info()) 366 except SkipTest as e: 367 self._addSkip(result, str(e)) 368 except: 369 result.addError(self, sys.exc_info()) 370 else: 371 success = True 372 373 try: 374 self.tearDown() 375 except KeyboardInterrupt: 376 raise 377 except: 378 result.addError(self, sys.exc_info()) 379 success = False 380 381 cleanUpSuccess = self.doCleanups() 382 success = success and cleanUpSuccess 383 if success: 384 result.addSuccess(self) 385 finally: 386 result.stopTest(self) 387 if orig_result is None: 388 stopTestRun = getattr(result, 'stopTestRun', None) 389 if stopTestRun is not None: 390 stopTestRun() 391 392 def doCleanups(self): 393 """Execute all cleanup functions. Normally called for you after 394 tearDown.""" 395 result = self._resultForDoCleanups 396 ok = True 397 while self._cleanups: 398 function, args, kwargs = self._cleanups.pop(-1) 399 try: 400 function(*args, **kwargs) 401 except KeyboardInterrupt: 402 raise 403 except: 404 ok = False 405 result.addError(self, sys.exc_info()) 406 return ok 407 408 def __call__(self, *args, **kwds): 409 return self.run(*args, **kwds) 410 411 def debug(self): 412 """Run the test without collecting errors in a TestResult""" 413 self.setUp() 414 getattr(self, self._testMethodName)() 415 self.tearDown() 416 while self._cleanups: 417 function, args, kwargs = self._cleanups.pop(-1) 418 function(*args, **kwargs) 419 420 def skipTest(self, reason): 421 """Skip this test.""" 422 raise SkipTest(reason) 423 424 def fail(self, msg=None): 425 """Fail immediately, with the given message.""" 426 raise self.failureException(msg) 427 428 def assertFalse(self, expr, msg=None): 429 """Check that the expression is false.""" 430 if expr: 431 msg = self._formatMessage(msg, "%s is not false" % safe_repr(expr)) 432 raise self.failureException(msg) 433 434 def assertTrue(self, expr, msg=None): 435 """Check that the expression is true.""" 436 if not expr: 437 msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr)) 438 raise self.failureException(msg) 439 440 def _formatMessage(self, msg, standardMsg): 441 """Honour the longMessage attribute when generating failure messages. 442 If longMessage is False this means: 443 * Use only an explicit message if it is provided 444 * Otherwise use the standard message for the assert 445 446 If longMessage is True: 447 * Use the standard message 448 * If an explicit message is provided, plus ' : ' and the explicit message 449 """ 450 if not self.longMessage: 451 return msg or standardMsg 452 if msg is None: 453 return standardMsg 454 try: 455 # don't switch to '{}' formatting in Python 2.X 456 # it changes the way unicode input is handled 457 return '%s : %s' % (standardMsg, msg) 458 except UnicodeDecodeError: 459 return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg)) 460 461 462 def assertRaises(self, excClass, callableObj=None, *args, **kwargs): 463 """Fail unless an exception of class excClass is raised 464 by callableObj when invoked with arguments args and keyword 465 arguments kwargs. If a different type of exception is 466 raised, it will not be caught, and the test case will be 467 deemed to have suffered an error, exactly as for an 468 unexpected exception. 469 470 If called with callableObj omitted or None, will return a 471 context object used like this:: 472 473 with self.assertRaises(SomeException): 474 do_something() 475 476 The context manager keeps a reference to the exception as 477 the 'exception' attribute. This allows you to inspect the 478 exception after the assertion:: 479 480 with self.assertRaises(SomeException) as cm: 481 do_something() 482 the_exception = cm.exception 483 self.assertEqual(the_exception.error_code, 3) 484 """ 485 context = _AssertRaisesContext(excClass, self) 486 if callableObj is None: 487 return context 488 with context: 489 callableObj(*args, **kwargs) 490 491 def _getAssertEqualityFunc(self, first, second): 492 """Get a detailed comparison function for the types of the two args. 493 494 Returns: A callable accepting (first, second, msg=None) that will 495 raise a failure exception if first != second with a useful human 496 readable error message for those types. 497 """ 498 # 499 # NOTE(gregory.p.smith): I considered isinstance(first, type(second)) 500 # and vice versa. I opted for the conservative approach in case 501 # subclasses are not intended to be compared in detail to their super 502 # class instances using a type equality func. This means testing 503 # subtypes won't automagically use the detailed comparison. Callers 504 # should use their type specific assertSpamEqual method to compare 505 # subclasses if the detailed comparison is desired and appropriate. 506 # See the discussion in http://bugs.python.org/issue2578. 507 # 508 if type(first) is type(second): 509 asserter = self._type_equality_funcs.get(type(first)) 510 if asserter is not None: 511 if isinstance(asserter, basestring): 512 asserter = getattr(self, asserter) 513 return asserter 514 515 return self._baseAssertEqual 516 517 def _baseAssertEqual(self, first, second, msg=None): 518 """The default assertEqual implementation, not type specific.""" 519 if not first == second: 520 standardMsg = '%s != %s' % (safe_repr(first), safe_repr(second)) 521 msg = self._formatMessage(msg, standardMsg) 522 raise self.failureException(msg) 523 524 def assertEqual(self, first, second, msg=None): 525 """Fail if the two objects are unequal as determined by the '==' 526 operator. 527 """ 528 assertion_func = self._getAssertEqualityFunc(first, second) 529 assertion_func(first, second, msg=msg) 530 531 def assertNotEqual(self, first, second, msg=None): 532 """Fail if the two objects are equal as determined by the '!=' 533 operator. 534 """ 535 if not first != second: 536 msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first), 537 safe_repr(second))) 538 raise self.failureException(msg) 539 540 541 def assertAlmostEqual(self, first, second, places=None, msg=None, delta=None): 542 """Fail if the two objects are unequal as determined by their 543 difference rounded to the given number of decimal places 544 (default 7) and comparing to zero, or by comparing that the 545 between the two objects is more than the given delta. 546 547 Note that decimal places (from zero) are usually not the same 548 as significant digits (measured from the most signficant digit). 549 550 If the two objects compare equal then they will automatically 551 compare almost equal. 552 """ 553 if first == second: 554 # shortcut 555 return 556 if delta is not None and places is not None: 557 raise TypeError("specify delta or places not both") 558 559 if delta is not None: 560 if abs(first - second) <= delta: 561 return 562 563 standardMsg = '%s != %s within %s delta' % (safe_repr(first), 564 safe_repr(second), 565 safe_repr(delta)) 566 else: 567 if places is None: 568 places = 7 569 570 if round(abs(second-first), places) == 0: 571 return 572 573 standardMsg = '%s != %s within %r places' % (safe_repr(first), 574 safe_repr(second), 575 places) 576 msg = self._formatMessage(msg, standardMsg) 577 raise self.failureException(msg) 578 579 def assertNotAlmostEqual(self, first, second, places=None, msg=None, delta=None): 580 """Fail if the two objects are equal as determined by their 581 difference rounded to the given number of decimal places 582 (default 7) and comparing to zero, or by comparing that the 583 between the two objects is less than the given delta. 584 585 Note that decimal places (from zero) are usually not the same 586 as significant digits (measured from the most signficant digit). 587 588 Objects that are equal automatically fail. 589 """ 590 if delta is not None and places is not None: 591 raise TypeError("specify delta or places not both") 592 if delta is not None: 593 if not (first == second) and abs(first - second) > delta: 594 return 595 standardMsg = '%s == %s within %s delta' % (safe_repr(first), 596 safe_repr(second), 597 safe_repr(delta)) 598 else: 599 if places is None: 600 places = 7 601 if not (first == second) and round(abs(second-first), places) != 0: 602 return 603 standardMsg = '%s == %s within %r places' % (safe_repr(first), 604 safe_repr(second), 605 places) 606 607 msg = self._formatMessage(msg, standardMsg) 608 raise self.failureException(msg) 609 610 # Synonyms for assertion methods 611 612 # The plurals are undocumented. Keep them that way to discourage use. 613 # Do not add more. Do not remove. 614 # Going through a deprecation cycle on these would annoy many people. 615 assertEquals = assertEqual 616 assertNotEquals = assertNotEqual 617 assertAlmostEquals = assertAlmostEqual 618 assertNotAlmostEquals = assertNotAlmostEqual 619 assert_ = assertTrue 620 621 # These fail* assertion method names are pending deprecation and will 622 # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578 623 def _deprecate(original_func): 624 def deprecated_func(*args, **kwargs): 625 warnings.warn( 626 # 'Please use {0} instead.'.format(original_func.__name__), 627 'Please use %s instead.' % (original_func.__name__), 628 PendingDeprecationWarning, 2) 629 return original_func(*args, **kwargs) 630 return deprecated_func 631 632 failUnlessEqual = _deprecate(assertEqual) 633 failIfEqual = _deprecate(assertNotEqual) 634 failUnlessAlmostEqual = _deprecate(assertAlmostEqual) 635 failIfAlmostEqual = _deprecate(assertNotAlmostEqual) 636 failUnless = _deprecate(assertTrue) 637 failUnlessRaises = _deprecate(assertRaises) 638 failIf = _deprecate(assertFalse) 639 640 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None): 641 """An equality assertion for ordered sequences (like lists and tuples). 642 643 For the purposes of this function, a valid ordered sequence type is one 644 which can be indexed, has a length, and has an equality operator. 645 646 Args: 647 seq1: The first sequence to compare. 648 seq2: The second sequence to compare. 649 seq_type: The expected datatype of the sequences, or None if no 650 datatype should be enforced. 651 msg: Optional message to use on failure instead of a list of 652 differences. 653 """ 654 if seq_type is not None: 655 seq_type_name = seq_type.__name__ 656 if not isinstance(seq1, seq_type): 657 raise self.failureException('First sequence is not a %s: %s' 658 % (seq_type_name, safe_repr(seq1))) 659 if not isinstance(seq2, seq_type): 660 raise self.failureException('Second sequence is not a %s: %s' 661 % (seq_type_name, safe_repr(seq2))) 662 else: 663 seq_type_name = "sequence" 664 665 differing = None 666 try: 667 len1 = len(seq1) 668 except (TypeError, NotImplementedError): 669 differing = 'First %s has no length. Non-sequence?' % ( 670 seq_type_name) 671 672 if differing is None: 673 try: 674 len2 = len(seq2) 675 except (TypeError, NotImplementedError): 676 differing = 'Second %s has no length. Non-sequence?' % ( 677 seq_type_name) 678 679 if differing is None: 680 if seq1 == seq2: 681 return 682 683 seq1_repr = safe_repr(seq1) 684 seq2_repr = safe_repr(seq2) 685 if len(seq1_repr) > 30: 686 seq1_repr = seq1_repr[:30] + '...' 687 if len(seq2_repr) > 30: 688 seq2_repr = seq2_repr[:30] + '...' 689 elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr) 690 differing = '%ss differ: %s != %s\n' % elements 691 692 for i in xrange(min(len1, len2)): 693 try: 694 item1 = seq1[i] 695 except (TypeError, IndexError, NotImplementedError): 696 differing += ('\nUnable to index element %d of first %s\n' % 697 (i, seq_type_name)) 698 break 699 700 try: 701 item2 = seq2[i] 702 except (TypeError, IndexError, NotImplementedError): 703 differing += ('\nUnable to index element %d of second %s\n' % 704 (i, seq_type_name)) 705 break 706 707 if item1 != item2: 708 differing += ('\nFirst differing element %d:\n%s\n%s\n' % 709 (i, safe_repr(item1), safe_repr(item2))) 710 break 711 else: 712 if (len1 == len2 and seq_type is None and 713 type(seq1) != type(seq2)): 714 # The sequences are the same, but have differing types. 715 return 716 717 if len1 > len2: 718 differing += ('\nFirst %s contains %d additional ' 719 'elements.\n' % (seq_type_name, len1 - len2)) 720 try: 721 differing += ('First extra element %d:\n%s\n' % 722 (len2, safe_repr(seq1[len2]))) 723 except (TypeError, IndexError, NotImplementedError): 724 differing += ('Unable to index element %d ' 725 'of first %s\n' % (len2, seq_type_name)) 726 elif len1 < len2: 727 differing += ('\nSecond %s contains %d additional ' 728 'elements.\n' % (seq_type_name, len2 - len1)) 729 try: 730 differing += ('First extra element %d:\n%s\n' % 731 (len1, safe_repr(seq2[len1]))) 732 except (TypeError, IndexError, NotImplementedError): 733 differing += ('Unable to index element %d ' 734 'of second %s\n' % (len1, seq_type_name)) 735 standardMsg = differing 736 diffMsg = '\n' + '\n'.join( 737 difflib.ndiff(pprint.pformat(seq1).splitlines(), 738 pprint.pformat(seq2).splitlines())) 739 standardMsg = self._truncateMessage(standardMsg, diffMsg) 740 msg = self._formatMessage(msg, standardMsg) 741 self.fail(msg) 742 743 def _truncateMessage(self, message, diff): 744 max_diff = self.maxDiff 745 if max_diff is None or len(diff) <= max_diff: 746 return message + diff 747 return message + (DIFF_OMITTED % len(diff)) 748 749 def assertListEqual(self, list1, list2, msg=None): 750 """A list-specific equality assertion. 751 752 Args: 753 list1: The first list to compare. 754 list2: The second list to compare. 755 msg: Optional message to use on failure instead of a list of 756 differences. 757 758 """ 759 self.assertSequenceEqual(list1, list2, msg, seq_type=list) 760 761 def assertTupleEqual(self, tuple1, tuple2, msg=None): 762 """A tuple-specific equality assertion. 763 764 Args: 765 tuple1: The first tuple to compare. 766 tuple2: The second tuple to compare. 767 msg: Optional message to use on failure instead of a list of 768 differences. 769 """ 770 self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple) 771 772 def assertSetEqual(self, set1, set2, msg=None): 773 """A set-specific equality assertion. 774 775 Args: 776 set1: The first set to compare. 777 set2: The second set to compare. 778 msg: Optional message to use on failure instead of a list of 779 differences. 780 781 assertSetEqual uses ducktyping to support different types of sets, and 782 is optimized for sets specifically (parameters must support a 783 difference method). 784 """ 785 try: 786 difference1 = set1.difference(set2) 787 except TypeError, e: 788 self.fail('invalid type when attempting set difference: %s' % e) 789 except AttributeError, e: 790 self.fail('first argument does not support set difference: %s' % e) 791 792 try: 793 difference2 = set2.difference(set1) 794 except TypeError, e: 795 self.fail('invalid type when attempting set difference: %s' % e) 796 except AttributeError, e: 797 self.fail('second argument does not support set difference: %s' % e) 798 799 if not (difference1 or difference2): 800 return 801 802 lines = [] 803 if difference1: 804 lines.append('Items in the first set but not the second:') 805 for item in difference1: 806 lines.append(repr(item)) 807 if difference2: 808 lines.append('Items in the second set but not the first:') 809 for item in difference2: 810 lines.append(repr(item)) 811 812 standardMsg = '\n'.join(lines) 813 self.fail(self._formatMessage(msg, standardMsg)) 814 815 def assertIn(self, member, container, msg=None): 816 """Just like self.assertTrue(a in b), but with a nicer default message.""" 817 if member not in container: 818 standardMsg = '%s not found in %s' % (safe_repr(member), 819 safe_repr(container)) 820 self.fail(self._formatMessage(msg, standardMsg)) 821 822 def assertNotIn(self, member, container, msg=None): 823 """Just like self.assertTrue(a not in b), but with a nicer default message.""" 824 if member in container: 825 standardMsg = '%s unexpectedly found in %s' % (safe_repr(member), 826 safe_repr(container)) 827 self.fail(self._formatMessage(msg, standardMsg)) 828 829 def assertIs(self, expr1, expr2, msg=None): 830 """Just like self.assertTrue(a is b), but with a nicer default message.""" 831 if expr1 is not expr2: 832 standardMsg = '%s is not %s' % (safe_repr(expr1), 833 safe_repr(expr2)) 834 self.fail(self._formatMessage(msg, standardMsg)) 835 836 def assertIsNot(self, expr1, expr2, msg=None): 837 """Just like self.assertTrue(a is not b), but with a nicer default message.""" 838 if expr1 is expr2: 839 standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),) 840 self.fail(self._formatMessage(msg, standardMsg)) 841 842 def assertDictEqual(self, d1, d2, msg=None): 843 self.assertIsInstance(d1, dict, 'First argument is not a dictionary') 844 self.assertIsInstance(d2, dict, 'Second argument is not a dictionary') 845 846 if d1 != d2: 847 standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True)) 848 diff = ('\n' + '\n'.join(difflib.ndiff( 849 pprint.pformat(d1).splitlines(), 850 pprint.pformat(d2).splitlines()))) 851 standardMsg = self._truncateMessage(standardMsg, diff) 852 self.fail(self._formatMessage(msg, standardMsg)) 853 854 def assertDictContainsSubset(self, expected, actual, msg=None): 855 """Checks whether actual is a superset of expected.""" 856 missing = [] 857 mismatched = [] 858 for key, value in expected.iteritems(): 859 if key not in actual: 860 missing.append(key) 861 elif value != actual[key]: 862 mismatched.append('%s, expected: %s, actual: %s' % 863 (safe_repr(key), safe_repr(value), 864 safe_repr(actual[key]))) 865 866 if not (missing or mismatched): 867 return 868 869 standardMsg = '' 870 if missing: 871 standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in 872 missing) 873 if mismatched: 874 if standardMsg: 875 standardMsg += '; ' 876 standardMsg += 'Mismatched values: %s' % ','.join(mismatched) 877 878 self.fail(self._formatMessage(msg, standardMsg)) 879 880 def assertItemsEqual(self, expected_seq, actual_seq, msg=None): 881 """An unordered sequence specific comparison. It asserts that 882 actual_seq and expected_seq have the same element counts. 883 Equivalent to:: 884 885 self.assertEqual(Counter(iter(actual_seq)), 886 Counter(iter(expected_seq))) 887 888 Asserts that each element has the same count in both sequences. 889 Example: 890 - [0, 1, 1] and [1, 0, 1] compare equal. 891 - [0, 0, 1] and [0, 1] compare unequal. 892 """ 893 first_seq, second_seq = list(expected_seq), list(actual_seq) 894 with warnings.catch_warnings(): 895 if sys.py3kwarning: 896 # Silence Py3k warning raised during the sorting 897 for _msg in ["(code|dict|type) inequality comparisons", 898 "builtin_function_or_method order comparisons", 899 "comparing unequal types"]: 900 warnings.filterwarnings("ignore", _msg, DeprecationWarning) 901 try: 902 first = collections.Counter(first_seq) 903 second = collections.Counter(second_seq) 904 except TypeError: 905 # Handle case with unhashable elements 906 differences = _count_diff_all_purpose(first_seq, second_seq) 907 else: 908 if first == second: 909 return 910 differences = _count_diff_hashable(first_seq, second_seq) 911 912 if differences: 913 standardMsg = 'Element counts were not equal:\n' 914 lines = ['First has %d, Second has %d: %r' % diff for diff in differences] 915 diffMsg = '\n'.join(lines) 916 standardMsg = self._truncateMessage(standardMsg, diffMsg) 917 msg = self._formatMessage(msg, standardMsg) 918 self.fail(msg) 919 920 def assertMultiLineEqual(self, first, second, msg=None): 921 """Assert that two multi-line strings are equal.""" 922 self.assertIsInstance(first, basestring, 923 'First argument is not a string') 924 self.assertIsInstance(second, basestring, 925 'Second argument is not a string') 926 927 if first != second: 928 # don't use difflib if the strings are too long 929 if (len(first) > self._diffThreshold or 930 len(second) > self._diffThreshold): 931 self._baseAssertEqual(first, second, msg) 932 firstlines = first.splitlines(True) 933 secondlines = second.splitlines(True) 934 if len(firstlines) == 1 and first.strip('\r\n') == first: 935 firstlines = [first + '\n'] 936 secondlines = [second + '\n'] 937 standardMsg = '%s != %s' % (safe_repr(first, True), 938 safe_repr(second, True)) 939 diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines)) 940 standardMsg = self._truncateMessage(standardMsg, diff) 941 self.fail(self._formatMessage(msg, standardMsg)) 942 943 def assertLess(self, a, b, msg=None): 944 """Just like self.assertTrue(a < b), but with a nicer default message.""" 945 if not a < b: 946 standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b)) 947 self.fail(self._formatMessage(msg, standardMsg)) 948 949 def assertLessEqual(self, a, b, msg=None): 950 """Just like self.assertTrue(a <= b), but with a nicer default message.""" 951 if not a <= b: 952 standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b)) 953 self.fail(self._formatMessage(msg, standardMsg)) 954 955 def assertGreater(self, a, b, msg=None): 956 """Just like self.assertTrue(a > b), but with a nicer default message.""" 957 if not a > b: 958 standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b)) 959 self.fail(self._formatMessage(msg, standardMsg)) 960 961 def assertGreaterEqual(self, a, b, msg=None): 962 """Just like self.assertTrue(a >= b), but with a nicer default message.""" 963 if not a >= b: 964 standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b)) 965 self.fail(self._formatMessage(msg, standardMsg)) 966 967 def assertIsNone(self, obj, msg=None): 968 """Same as self.assertTrue(obj is None), with a nicer default message.""" 969 if obj is not None: 970 standardMsg = '%s is not None' % (safe_repr(obj),) 971 self.fail(self._formatMessage(msg, standardMsg)) 972 973 def assertIsNotNone(self, obj, msg=None): 974 """Included for symmetry with assertIsNone.""" 975 if obj is None: 976 standardMsg = 'unexpectedly None' 977 self.fail(self._formatMessage(msg, standardMsg)) 978 979 def assertIsInstance(self, obj, cls, msg=None): 980 """Same as self.assertTrue(isinstance(obj, cls)), with a nicer 981 default message.""" 982 if not isinstance(obj, cls): 983 standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls) 984 self.fail(self._formatMessage(msg, standardMsg)) 985 986 def assertNotIsInstance(self, obj, cls, msg=None): 987 """Included for symmetry with assertIsInstance.""" 988 if isinstance(obj, cls): 989 standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls) 990 self.fail(self._formatMessage(msg, standardMsg)) 991 992 def assertRaisesRegexp(self, expected_exception, expected_regexp, 993 callable_obj=None, *args, **kwargs): 994 """Asserts that the message in a raised exception matches a regexp. 995 996 Args: 997 expected_exception: Exception class expected to be raised. 998 expected_regexp: Regexp (re pattern object or string) expected 999 to be found in error message. 1000 callable_obj: Function to be called. 1001 args: Extra args. 1002 kwargs: Extra kwargs. 1003 """ 1004 if expected_regexp is not None: 1005 expected_regexp = re.compile(expected_regexp) 1006 context = _AssertRaisesContext(expected_exception, self, expected_regexp) 1007 if callable_obj is None: 1008 return context 1009 with context: 1010 callable_obj(*args, **kwargs) 1011 1012 def assertRegexpMatches(self, text, expected_regexp, msg=None): 1013 """Fail the test unless the text matches the regular expression.""" 1014 if isinstance(expected_regexp, basestring): 1015 expected_regexp = re.compile(expected_regexp) 1016 if not expected_regexp.search(text): 1017 msg = msg or "Regexp didn't match" 1018 msg = '%s: %r not found in %r' % (msg, expected_regexp.pattern, text) 1019 raise self.failureException(msg) 1020 1021 def assertNotRegexpMatches(self, text, unexpected_regexp, msg=None): 1022 """Fail the test if the text matches the regular expression.""" 1023 if isinstance(unexpected_regexp, basestring): 1024 unexpected_regexp = re.compile(unexpected_regexp) 1025 match = unexpected_regexp.search(text) 1026 if match: 1027 msg = msg or "Regexp matched" 1028 msg = '%s: %r matches %r in %r' % (msg, 1029 text[match.start():match.end()], 1030 unexpected_regexp.pattern, 1031 text) 1032 raise self.failureException(msg) 1033 1034 1035 class FunctionTestCase(TestCase): 1036 """A test case that wraps a test function. 1037 1038 This is useful for slipping pre-existing test functions into the 1039 unittest framework. Optionally, set-up and tidy-up functions can be 1040 supplied. As with TestCase, the tidy-up ('tearDown') function will 1041 always be called if the set-up ('setUp') function ran successfully. 1042 """ 1043 1044 def __init__(self, testFunc, setUp=None, tearDown=None, description=None): 1045 super(FunctionTestCase, self).__init__() 1046 self._setUpFunc = setUp 1047 self._tearDownFunc = tearDown 1048 self._testFunc = testFunc 1049 self._description = description 1050 1051 def setUp(self): 1052 if self._setUpFunc is not None: 1053 self._setUpFunc() 1054 1055 def tearDown(self): 1056 if self._tearDownFunc is not None: 1057 self._tearDownFunc() 1058 1059 def runTest(self): 1060 self._testFunc() 1061 1062 def id(self): 1063 return self._testFunc.__name__ 1064 1065 def __eq__(self, other): 1066 if not isinstance(other, self.__class__): 1067 return NotImplemented 1068 1069 return self._setUpFunc == other._setUpFunc and \ 1070 self._tearDownFunc == other._tearDownFunc and \ 1071 self._testFunc == other._testFunc and \ 1072 self._description == other._description 1073 1074 def __ne__(self, other): 1075 return not self == other 1076 1077 def __hash__(self): 1078 return hash((type(self), self._setUpFunc, self._tearDownFunc, 1079 self._testFunc, self._description)) 1080 1081 def __str__(self): 1082 return "%s (%s)" % (strclass(self.__class__), 1083 self._testFunc.__name__) 1084 1085 def __repr__(self): 1086 return "<%s tec=%s>" % (strclass(self.__class__), 1087 self._testFunc) 1088 1089 def shortDescription(self): 1090 if self._description is not None: 1091 return self._description 1092 # doc = self._testFunc.__doc__ 1093 return doc and doc.split("\n")[0].strip() or None