unittest.py revision 6f7d363407f1915536722883e4bfb856fc143abf
1#!/usr/bin/env python 2''' 3Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's 4Smalltalk testing framework. 5 6This module contains the core framework classes that form the basis of 7specific test cases and suites (TestCase, TestSuite etc.), and also a 8text-based utility class for running the tests and reporting the results 9 (TextTestRunner). 10 11Simple usage: 12 13 import unittest 14 15 class IntegerArithmenticTestCase(unittest.TestCase): 16 def testAdd(self): ## test method names begin 'test*' 17 self.assertEqual((1 + 2), 3) 18 self.assertEqual(0 + 1, 1) 19 def testMultiply(self): 20 self.assertEqual((0 * 10), 0) 21 self.assertEqual((5 * 8), 40) 22 23 if __name__ == '__main__': 24 unittest.main() 25 26Further information is available in the bundled documentation, and from 27 28 http://docs.python.org/library/unittest.html 29 30Copyright (c) 1999-2003 Steve Purcell 31Copyright (c) 2003-2009 Python Software Foundation 32Copyright (c) 2009 Garrett Cooper 33This module is free software, and you may redistribute it and/or modify 34it under the same terms as Python itself, so long as this copyright message 35and disclaimer are retained in their original form. 36 37IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 38SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF 39THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 40DAMAGE. 41 42THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 43LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 44PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, 45AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, 46SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 47 48Garrett: This module was backported using source from r71263 with fixes noted 49in Issue 5771. 50''' 51 52import difflib 53try: 54 import functools 55except ImportError: 56 # Most likely using 2.4.x 57 raise ImportError("Failed to import functools (most likely because you're " 58 "using 2.4.x. Please go to " 59 "http://pypi.python.org/simple/functools/ to get the " 60 "package") 61 62import os 63import pprint 64import re 65import sys 66import time 67import traceback 68import types 69import warnings 70 71############################################################################## 72# Exported classes and functions 73############################################################################## 74__all__ = ['TestResult', 'TestCase', 'TestSuite', 'ClassTestSuite', 75 'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main', 76 'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless', 77 'expectedFailure'] 78 79# Expose obsolete functions for backwards compatibility 80__all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases']) 81 82 83############################################################################## 84# Backward compatibility 85############################################################################## 86 87def _CmpToKey(mycmp): 88 'Convert a cmp= function into a key= function' 89 class K(object): 90 def __init__(self, obj): 91 self.obj = obj 92 def __lt__(self, other): 93 return mycmp(self.obj, other.obj) == -1 94 return K 95 96############################################################################## 97# Test framework core 98############################################################################## 99 100def _strclass(cls): 101 return "%s.%s" % (cls.__module__, cls.__name__) 102 103 104class SkipTest(Exception): 105 """ 106 Raise this exception in a test to skip it. 107 108 Usually you can use TestResult.skip() or one of the skipping decorators 109 instead of raising this directly. 110 """ 111 pass 112 113class _ExpectedFailure(Exception): 114 """ 115 Raise this when a test is expected to fail. 116 117 This is an implementation detail. 118 """ 119 120 def __init__(self, exc_info): 121 super(_ExpectedFailure, self).__init__() 122 self.exc_info = exc_info 123 124class _UnexpectedSuccess(Exception): 125 """ 126 The test was supposed to fail, but it didn't! 127 """ 128 pass 129 130def _id(obj): 131 return obj 132 133def skip(reason): 134 """ 135 Unconditionally skip a test. 136 """ 137 def decorator(test_item): 138 if isinstance(test_item, type) and issubclass(test_item, TestCase): 139 test_item.__unittest_skip__ = True 140 test_item.__unittest_skip_why__ = reason 141 return test_item 142 @functools.wraps(test_item) 143 def skip_wrapper(*args, **kwargs): 144 raise SkipTest(reason) 145 return skip_wrapper 146 return decorator 147 148def skipIf(condition, reason): 149 """ 150 Skip a test if the condition is true. 151 """ 152 if condition: 153 return skip(reason) 154 return _id 155 156def skipUnless(condition, reason): 157 """ 158 Skip a test unless the condition is true. 159 """ 160 if not condition: 161 return skip(reason) 162 return _id 163 164 165def expectedFailure(func): 166 @functools.wraps(func) 167 def wrapper(*args, **kwargs): 168 try: 169 func(*args, **kwargs) 170 except Exception: 171 raise _ExpectedFailure(sys.exc_info()) 172 raise _UnexpectedSuccess 173 return wrapper 174 175__unittest = 1 176 177class TestResult(object): 178 """Holder for test result information. 179 180 Test results are automatically managed by the TestCase and TestSuite 181 classes, and do not need to be explicitly manipulated by writers of tests. 182 183 Each instance holds the total number of tests run, and collections of 184 failures and errors that occurred among those test runs. The collections 185 contain tuples of (testcase, exceptioninfo), where exceptioninfo is the 186 formatted traceback of the error that occurred. 187 """ 188 def __init__(self): 189 self.failures = [] 190 self.errors = [] 191 self.testsRun = 0 192 self.skipped = [] 193 self.expectedFailures = [] 194 self.unexpectedSuccesses = [] 195 self.shouldStop = False 196 197 def startTest(self, test): 198 "Called when the given test is about to be run" 199 self.testsRun = self.testsRun + 1 200 201 def stopTest(self, test): 202 "Called when the given test has been run" 203 pass 204 205 def addError(self, test, err): 206 """Called when an error has occurred. 'err' is a tuple of values as 207 returned by sys.exc_info(). 208 """ 209 self.errors.append((test, self._exc_info_to_string(err, test))) 210 211 def addFailure(self, test, err): 212 """Called when an error has occurred. 'err' is a tuple of values as 213 returned by sys.exc_info().""" 214 self.failures.append((test, self._exc_info_to_string(err, test))) 215 216 def addSuccess(self, test): 217 "Called when a test has completed successfully" 218 pass 219 220 def addSkip(self, test, reason): 221 """Called when a test is skipped.""" 222 self.skipped.append((test, reason)) 223 224 def addExpectedFailure(self, test, err): 225 """Called when an expected failure/error occured.""" 226 self.expectedFailures.append( 227 (test, self._exc_info_to_string(err, test))) 228 229 def addUnexpectedSuccess(self, test): 230 """Called when a test was expected to fail, but succeed.""" 231 self.unexpectedSuccesses.append(test) 232 233 def wasSuccessful(self): 234 "Tells whether or not this result was a success" 235 return len(self.failures) == len(self.errors) == 0 236 237 def stop(self): 238 "Indicates that the tests should be aborted" 239 self.shouldStop = True 240 241 def _exc_info_to_string(self, err, test): 242 """Converts a sys.exc_info()-style tuple of values into a string.""" 243 exctype, value, tb = err 244 # Skip test runner traceback levels 245 while tb and self._is_relevant_tb_level(tb): 246 tb = tb.tb_next 247 if exctype is test.failureException: 248 # Skip assert*() traceback levels 249 length = self._count_relevant_tb_levels(tb) 250 return ''.join(traceback.format_exception(exctype, value, tb, length)) 251 return ''.join(traceback.format_exception(exctype, value, tb)) 252 253 def _is_relevant_tb_level(self, tb): 254 return '__unittest' in tb.tb_frame.f_globals 255 256 def _count_relevant_tb_levels(self, tb): 257 length = 0 258 while tb and not self._is_relevant_tb_level(tb): 259 length += 1 260 tb = tb.tb_next 261 return length 262 263 def __repr__(self): 264 return "<%s run=%i errors=%i failures=%i>" % \ 265 (_strclass(self.__class__), self.testsRun, len(self.errors), 266 len(self.failures)) 267 268 269class _AssertRaisesContext(object): 270 """A context manager used to implement TestCase.assertRaises* methods.""" 271 272 def __init__(self, expected, test_case, expected_regexp=None): 273 self.expected = expected 274 self.failureException = test_case.failureException 275 self.expected_regex = expected_regexp 276 277 def __enter__(self): 278 pass 279 280 def __exit__(self, exc_type, exc_value, tb): 281 if exc_type is None: 282 try: 283 exc_name = self.expected.__name__ 284 except AttributeError: 285 exc_name = str(self.expected) 286 raise self.failureException( 287 "%s not raised" % exc_name) 288 if not issubclass(exc_type, self.expected): 289 # let unexpected exceptions pass through 290 return False 291 if self.expected_regex is None: 292 return True 293 294 expected_regexp = self.expected_regex 295 if isinstance(expected_regexp, basestring): 296 expected_regexp = re.compile(expected_regexp) 297 if not expected_regexp.search(str(exc_value)): 298 raise self.failureException('"%s" does not match "%s"' % 299 (expected_regexp.pattern, str(exc_value))) 300 return True 301 302 303class _AssertWrapper(object): 304 """Wrap entries in the _type_equality_funcs registry to make them deep 305 copyable.""" 306 307 def __init__(self, function): 308 self.function = function 309 310 def __deepcopy__(self, memo): 311 memo[id(self)] = self 312 313 314class TestCase(object): 315 """A class whose instances are single test cases. 316 317 By default, the test code itself should be placed in a method named 318 'runTest'. 319 320 If the fixture may be used for many test cases, create as 321 many test methods as are needed. When instantiating such a TestCase 322 subclass, specify in the constructor arguments the name of the test method 323 that the instance is to execute. 324 325 Test authors should subclass TestCase for their own tests. Construction 326 and deconstruction of the test's environment ('fixture') can be 327 implemented by overriding the 'setUp' and 'tearDown' methods respectively. 328 329 If it is necessary to override the __init__ method, the base class 330 __init__ method must always be called. It is important that subclasses 331 should not change the signature of their __init__ method, since instances 332 of the classes are instantiated automatically by parts of the framework 333 in order to be run. 334 """ 335 336 # This attribute determines which exception will be raised when 337 # the instance's assertion methods fail; test methods raising this 338 # exception will be deemed to have 'failed' rather than 'errored' 339 340 failureException = AssertionError 341 342 # This attribute determines whether long messages (including repr of 343 # objects used in assert methods) will be printed on failure in *addition* 344 # to any explicit message passed. 345 346 longMessage = False 347 348 349 def __init__(self, methodName='runTest'): 350 """Create an instance of the class that will use the named test 351 method when executed. Raises a ValueError if the instance does 352 not have a method with the specified name. 353 """ 354 self._testMethodName = methodName 355 try: 356 testMethod = getattr(self, methodName) 357 except AttributeError: 358 raise ValueError("no such test method in %s: %s" % \ 359 (self.__class__, methodName)) 360 self._testMethodDoc = testMethod.__doc__ 361 362 # Map types to custom assertEqual functions that will compare 363 # instances of said type in more detail to generate a more useful 364 # error message. 365 self._type_equality_funcs = {} 366 self.addTypeEqualityFunc(dict, self.assertDictEqual) 367 self.addTypeEqualityFunc(list, self.assertListEqual) 368 self.addTypeEqualityFunc(tuple, self.assertTupleEqual) 369 self.addTypeEqualityFunc(set, self.assertSetEqual) 370 self.addTypeEqualityFunc(frozenset, self.assertSetEqual) 371 372 def addTypeEqualityFunc(self, typeobj, function): 373 """Add a type specific assertEqual style function to compare a type. 374 375 This method is for use by TestCase subclasses that need to register 376 their own type equality functions to provide nicer error messages. 377 378 Args: 379 typeobj: The data type to call this function on when both values 380 are of the same type in assertEqual(). 381 function: The callable taking two arguments and an optional 382 msg= argument that raises self.failureException with a 383 useful error message when the two arguments are not equal. 384 """ 385 self._type_equality_funcs[typeobj] = _AssertWrapper(function) 386 387 def setUp(self): 388 "Hook method for setting up the test fixture before exercising it." 389 pass 390 391 def tearDown(self): 392 "Hook method for deconstructing the test fixture after testing it." 393 pass 394 395 def countTestCases(self): 396 return 1 397 398 def defaultTestResult(self): 399 return TestResult() 400 401 def shortDescription(self): 402 """Returns both the test method name and first line of its docstring. 403 404 If no docstring is given, only returns the method name. 405 406 This method overrides unittest.TestCase.shortDescription(), which 407 only returns the first line of the docstring, obscuring the name 408 of the test upon failure. 409 """ 410 desc = str(self) 411 doc_first_line = None 412 413 if self._testMethodDoc: 414 doc_first_line = self._testMethodDoc.split("\n")[0].strip() 415 if doc_first_line: 416 desc = '\n'.join((desc, doc_first_line)) 417 return desc 418 419 def id(self): 420 return "%s.%s" % (_strclass(self.__class__), self._testMethodName) 421 422 def __eq__(self, other): 423 if type(self) is not type(other): 424 return NotImplemented 425 426 return self._testMethodName == other._testMethodName 427 428 def __ne__(self, other): 429 return not self == other 430 431 def __hash__(self): 432 return hash((type(self), self._testMethodName)) 433 434 def __str__(self): 435 return "%s (%s)" % (self._testMethodName, _strclass(self.__class__)) 436 437 def __repr__(self): 438 return "<%s testMethod=%s>" % \ 439 (_strclass(self.__class__), self._testMethodName) 440 441 def run(self, result=None): 442 if result is None: 443 result = self.defaultTestResult() 444 result.startTest(self) 445 testMethod = getattr(self, self._testMethodName) 446 try: 447 try: 448 self.setUp() 449 except SkipTest, e: 450 result.addSkip(self, str(e)) 451 return 452 except Exception: 453 result.addError(self, sys.exc_info()) 454 return 455 456 success = False 457 try: 458 testMethod() 459 except self.failureException: 460 result.addFailure(self, sys.exc_info()) 461 except _ExpectedFailure, e: 462 result.addExpectedFailure(self, e.exc_info) 463 except _UnexpectedSuccess: 464 result.addUnexpectedSuccess(self) 465 except SkipTest, e: 466 result.addSkip(self, str(e)) 467 except Exception: 468 result.addError(self, sys.exc_info()) 469 else: 470 success = True 471 472 try: 473 self.tearDown() 474 except Exception: 475 result.addError(self, sys.exc_info()) 476 success = False 477 if success: 478 result.addSuccess(self) 479 finally: 480 result.stopTest(self) 481 482 def __call__(self, *args, **kwds): 483 return self.run(*args, **kwds) 484 485 def debug(self): 486 """Run the test without collecting errors in a TestResult""" 487 self.setUp() 488 getattr(self, self._testMethodName)() 489 self.tearDown() 490 491 def skipTest(self, reason): 492 """Skip this test.""" 493 raise SkipTest(reason) 494 495 def fail(self, msg=None): 496 """Fail immediately, with the given message.""" 497 raise self.failureException(msg) 498 499 def assertFalse(self, expr, msg=None): 500 "Fail the test if the expression is true." 501 if expr: 502 msg = self._formatMessage(msg, "%r is not False" % expr) 503 raise self.failureException(msg) 504 505 def assertTrue(self, expr, msg=None): 506 """Fail the test unless the expression is true.""" 507 if not expr: 508 msg = self._formatMessage(msg, "%r is not True" % expr) 509 raise self.failureException(msg) 510 511 def _formatMessage(self, msg, standardMsg): 512 """Honour the longMessage attribute when generating failure messages. 513 If longMessage is False this means: 514 * Use only an explicit message if it is provided 515 * Otherwise use the standard message for the assert 516 517 If longMessage is True: 518 * Use the standard message 519 * If an explicit message is provided, plus ' : ' and the explicit message 520 """ 521 if not self.longMessage: 522 return msg or standardMsg 523 if msg is None: 524 return standardMsg 525 return standardMsg + ' : ' + msg 526 527 528 def assertRaises(self, excClass, callableObj=None, *args, **kwargs): 529 """Fail unless an exception of class excClass is thrown 530 by callableObj when invoked with arguments args and keyword 531 arguments kwargs. If a different type of exception is 532 thrown, it will not be caught, and the test case will be 533 deemed to have suffered an error, exactly as for an 534 unexpected exception. 535 536 If called with callableObj omitted or None, will return a 537 context object used like this:: 538 539 with self.assertRaises(some_error_class): 540 do_something() 541 """ 542 context = _AssertRaisesContext(excClass, self) 543 if callableObj is None: 544 return context 545 546 # XXX (garrcoop): `with context' isn't supported lexigram with 2.4/2.5, 547 # even though PEP 343 (sort of) implies that based on the publishing 548 # date. There may be another PEP which changed the syntax... 549 context.__enter__() 550 try: 551 callableObj(*args, **kwargs) 552 finally: 553 context.__exit__() 554 555 def _getAssertEqualityFunc(self, first, second): 556 """Get a detailed comparison function for the types of the two args. 557 558 Returns: A callable accepting (first, second, msg=None) that will 559 raise a failure exception if first != second with a useful human 560 readable error message for those types. 561 """ 562 # 563 # NOTE(gregory.p.smith): I considered isinstance(first, type(second)) 564 # and vice versa. I opted for the conservative approach in case 565 # subclasses are not intended to be compared in detail to their super 566 # class instances using a type equality func. This means testing 567 # subtypes won't automagically use the detailed comparison. Callers 568 # should use their type specific assertSpamEqual method to compare 569 # subclasses if the detailed comparison is desired and appropriate. 570 # See the discussion in http://bugs.python.org/issue2578. 571 # 572 if type(first) is type(second): 573 asserter = self._type_equality_funcs.get(type(first)) 574 if asserter is not None: 575 return asserter.function 576 577 return self._baseAssertEqual 578 579 def _baseAssertEqual(self, first, second, msg=None): 580 """The default assertEqual implementation, not type specific.""" 581 if not first == second: 582 standardMsg = '%r != %r' % (first, second) 583 msg = self._formatMessage(msg, standardMsg) 584 raise self.failureException(msg) 585 586 def assertEqual(self, first, second, msg=None): 587 """Fail if the two objects are unequal as determined by the '==' 588 operator. 589 """ 590 assertion_func = self._getAssertEqualityFunc(first, second) 591 assertion_func(first, second, msg=msg) 592 593 def assertNotEqual(self, first, second, msg=None): 594 """Fail if the two objects are equal as determined by the '==' 595 operator. 596 """ 597 if not first != second: 598 msg = self._formatMessage(msg, '%r == %r' % (first, second)) 599 raise self.failureException(msg) 600 601 def assertAlmostEqual(self, first, second, places=7, msg=None): 602 """Fail if the two objects are unequal as determined by their 603 difference rounded to the given number of decimal places 604 (default 7) and comparing to zero. 605 606 Note that decimal places (from zero) are usually not the same 607 as significant digits (measured from the most signficant digit). 608 """ 609 if round(abs(second-first), places) != 0: 610 standardMsg = '%r != %r within %r places' % (first, second, places) 611 msg = self._formatMessage(msg, standardMsg) 612 raise self.failureException(msg) 613 614 def assertNotAlmostEqual(self, first, second, places=7, msg=None): 615 """Fail if the two objects are equal as determined by their 616 difference rounded to the given number of decimal places 617 (default 7) and comparing to zero. 618 619 Note that decimal places (from zero) are usually not the same 620 as significant digits (measured from the most signficant digit). 621 """ 622 if round(abs(second-first), places) == 0: 623 standardMsg = '%r == %r within %r places' % (first, second, places) 624 msg = self._formatMessage(msg, standardMsg) 625 raise self.failureException(msg) 626 627 # Synonyms for assertion methods 628 629 # The plurals are undocumented. Keep them that way to discourage use. 630 # Do not add more. Do not remove. 631 # Going through a deprecation cycle on these would annoy many people. 632 assertEquals = assertEqual 633 assertNotEquals = assertNotEqual 634 assertAlmostEquals = assertAlmostEqual 635 assertNotAlmostEquals = assertNotAlmostEqual 636 assert_ = assertTrue 637 638 # These fail* assertion method names are pending deprecation and will 639 # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578 640 def _deprecate(original_func): 641 def deprecated_func(*args, **kwargs): 642 warnings.warn( 643 'Please use %s instead.' % original_func.__name__, 644 PendingDeprecationWarning, 2) 645 return original_func(*args, **kwargs) 646 return deprecated_func 647 648 failUnlessEqual = _deprecate(assertEqual) 649 failIfEqual = _deprecate(assertNotEqual) 650 failUnlessAlmostEqual = _deprecate(assertAlmostEqual) 651 failIfAlmostEqual = _deprecate(assertNotAlmostEqual) 652 failUnless = _deprecate(assertTrue) 653 failUnlessRaises = _deprecate(assertRaises) 654 failIf = _deprecate(assertFalse) 655 656 def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None): 657 """An equality assertion for ordered sequences (like lists and tuples). 658 659 For the purposes of this function, a valid orderd sequence type is one 660 which can be indexed, has a length, and has an equality operator. 661 662 Args: 663 seq1: The first sequence to compare. 664 seq2: The second sequence to compare. 665 seq_type: The expected datatype of the sequences, or None if no 666 datatype should be enforced. 667 msg: Optional message to use on failure instead of a list of 668 differences. 669 """ 670 if seq_type != None: 671 seq_type_name = seq_type.__name__ 672 if not isinstance(seq1, seq_type): 673 raise self.failureException('First sequence is not a %s: %r' 674 % (seq_type_name, seq1)) 675 if not isinstance(seq2, seq_type): 676 raise self.failureException('Second sequence is not a %s: %r' 677 % (seq_type_name, seq2)) 678 else: 679 seq_type_name = "sequence" 680 681 differing = None 682 try: 683 len1 = len(seq1) 684 except (TypeError, NotImplementedError): 685 differing = 'First %s has no length. Non-sequence?' % ( 686 seq_type_name) 687 688 if differing is None: 689 try: 690 len2 = len(seq2) 691 except (TypeError, NotImplementedError): 692 differing = 'Second %s has no length. Non-sequence?' % ( 693 seq_type_name) 694 695 if differing is None: 696 if seq1 == seq2: 697 return 698 699 for i in xrange(min(len1, len2)): 700 try: 701 item1 = seq1[i] 702 except (TypeError, IndexError, NotImplementedError): 703 differing = ('Unable to index element %d of first %s\n' % 704 (i, seq_type_name)) 705 break 706 707 try: 708 item2 = seq2[i] 709 except (TypeError, IndexError, NotImplementedError): 710 differing = ('Unable to index element %d of second %s\n' % 711 (i, seq_type_name)) 712 break 713 714 if item1 != item2: 715 differing = ('First differing element %d:\n%s\n%s\n' % 716 (i, item1, item2)) 717 break 718 else: 719 if (len1 == len2 and seq_type is None and 720 type(seq1) != type(seq2)): 721 # The sequences are the same, but have differing types. 722 return 723 # A catch-all message for handling arbitrary user-defined 724 # sequences. 725 differing = '%ss differ:\n' % seq_type_name.capitalize() 726 if len1 > len2: 727 differing = ('First %s contains %d additional ' 728 'elements.\n' % (seq_type_name, len1 - len2)) 729 try: 730 differing += ('First extra element %d:\n%s\n' % 731 (len2, seq1[len2])) 732 except (TypeError, IndexError, NotImplementedError): 733 differing += ('Unable to index element %d ' 734 'of first %s\n' % (len2, seq_type_name)) 735 elif len1 < len2: 736 differing = ('Second %s contains %d additional ' 737 'elements.\n' % (seq_type_name, len2 - len1)) 738 try: 739 differing += ('First extra element %d:\n%s\n' % 740 (len1, seq2[len1])) 741 except (TypeError, IndexError, NotImplementedError): 742 differing += ('Unable to index element %d ' 743 'of second %s\n' % (len1, seq_type_name)) 744 standardMsg = differing + '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(), 745 pprint.pformat(seq2).splitlines())) 746 msg = self._formatMessage(msg, standardMsg) 747 self.fail(msg) 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 For more general containership equality, assertSameElements will work 782 with things other than sets. This uses ducktyping to support 783 different types of sets, and is optimized for sets specifically 784 (parameters must support a difference method). 785 """ 786 try: 787 difference1 = set1.difference(set2) 788 except TypeError, e: 789 self.fail('invalid type when attempting set difference: %s' % e) 790 except AttributeError, e: 791 self.fail('first argument does not support set difference: %s' % e) 792 793 try: 794 difference2 = set2.difference(set1) 795 except TypeError, e: 796 self.fail('invalid type when attempting set difference: %s' % e) 797 except AttributeError, e: 798 self.fail('second argument does not support set difference: %s' % e) 799 800 if not (difference1 or difference2): 801 return 802 803 lines = [] 804 if difference1: 805 lines.append('Items in the first set but not the second:') 806 for item in difference1: 807 lines.append(repr(item)) 808 if difference2: 809 lines.append('Items in the second set but not the first:') 810 for item in difference2: 811 lines.append(repr(item)) 812 813 standardMsg = '\n'.join(lines) 814 self.fail(self._formatMessage(msg, standardMsg)) 815 816 def assertIn(self, member, container, msg=None): 817 """Just like self.assertTrue(a in b), but with a nicer default message.""" 818 if member not in container: 819 standardMsg = '%r not found in %r' % (member, 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 = '%r unexpectedly found in %r' % (member, container) 826 self.fail(self._formatMessage(msg, standardMsg)) 827 828 def assertIs(self, expr1, expr2, msg=None): 829 """Just like self.assertTrue(a is b), but with a nicer default message.""" 830 if expr1 is not expr2: 831 standardMsg = '%r is not %r' % (expr1, expr2) 832 self.fail(self._formatMessage(msg, standardMsg)) 833 834 def assertIsNot(self, expr1, expr2, msg=None): 835 """Just like self.assertTrue(a is not b), but with a nicer default message.""" 836 if expr1 is expr2: 837 standardMsg = 'unexpectedly identical: %r' % (expr1,) 838 self.fail(self._formatMessage(msg, standardMsg)) 839 840 def assertDictEqual(self, d1, d2, msg=None): 841 self.assert_(isinstance(d1, dict), 'First argument is not a dictionary') 842 self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary') 843 844 if d1 != d2: 845 standardMsg = ('\n' + '\n'.join(difflib.ndiff( 846 pprint.pformat(d1).splitlines(), 847 pprint.pformat(d2).splitlines()))) 848 self.fail(self._formatMessage(msg, standardMsg)) 849 850 def assertDictContainsSubset(self, expected, actual, msg=None): 851 """Checks whether actual is a superset of expected.""" 852 missing = [] 853 mismatched = [] 854 for key, value in expected.iteritems(): 855 if key not in actual: 856 missing.append(key) 857 elif value != actual[key]: 858 mismatched.append('%s, expected: %s, actual: %s' % (key, value, actual[key])) 859 860 if not (missing or mismatched): 861 return 862 863 standardMsg = '' 864 if missing: 865 standardMsg = 'Missing: %r' % ','.join(missing) 866 if mismatched: 867 if standardMsg: 868 standardMsg += '; ' 869 standardMsg += 'Mismatched values: %s' % ','.join(mismatched) 870 871 self.fail(self._formatMessage(msg, standardMsg)) 872 873 def assertSameElements(self, expected_seq, actual_seq, msg=None): 874 """An unordered sequence specific comparison. 875 876 Raises with an error message listing which elements of expected_seq 877 are missing from actual_seq and vice versa if any. 878 """ 879 try: 880 expected = set(expected_seq) 881 actual = set(actual_seq) 882 missing = list(expected.difference(actual)) 883 unexpected = list(actual.difference(expected)) 884 missing.sort() 885 unexpected.sort() 886 except TypeError: 887 # Fall back to slower list-compare if any of the objects are 888 # not hashable. 889 expected = list(expected_seq) 890 actual = list(actual_seq) 891 expected.sort() 892 actual.sort() 893 missing, unexpected = _SortedListDifference(expected, actual) 894 errors = [] 895 if missing: 896 errors.append('Expected, but missing:\n %r' % missing) 897 if unexpected: 898 errors.append('Unexpected, but present:\n %r' % unexpected) 899 if errors: 900 standardMsg = '\n'.join(errors) 901 self.fail(self._formatMessage(msg, standardMsg)) 902 903 def assertMultiLineEqual(self, first, second, msg=None): 904 """Assert that two multi-line strings are equal.""" 905 self.assert_(isinstance(first, basestring), ( 906 'First argument is not a string')) 907 self.assert_(isinstance(second, basestring), ( 908 'Second argument is not a string')) 909 910 if first != second: 911 standardMsg = '\n' + ''.join(difflib.ndiff(first.splitlines(True), second.splitlines(True))) 912 self.fail(self._formatMessage(msg, standardMsg)) 913 914 def assertLess(self, a, b, msg=None): 915 """Just like self.assertTrue(a < b), but with a nicer default message.""" 916 if not a < b: 917 standardMsg = '%r not less than %r' % (a, b) 918 self.fail(self._formatMessage(msg, standardMsg)) 919 920 def assertLessEqual(self, a, b, msg=None): 921 """Just like self.assertTrue(a <= b), but with a nicer default message.""" 922 if not a <= b: 923 standardMsg = '%r not less than or equal to %r' % (a, b) 924 self.fail(self._formatMessage(msg, standardMsg)) 925 926 def assertGreater(self, a, b, msg=None): 927 """Just like self.assertTrue(a > b), but with a nicer default message.""" 928 if not a > b: 929 standardMsg = '%r not greater than %r' % (a, b) 930 self.fail(self._formatMessage(msg, standardMsg)) 931 932 def assertGreaterEqual(self, a, b, msg=None): 933 """Just like self.assertTrue(a >= b), but with a nicer default message.""" 934 if not a >= b: 935 standardMsg = '%r not greater than or equal to %r' % (a, b) 936 self.fail(self._formatMessage(msg, standardMsg)) 937 938 def assertIsNone(self, obj, msg=None): 939 """Same as self.assertTrue(obj is None), with a nicer default message.""" 940 if obj is not None: 941 standardMsg = '%r is not None' % obj 942 self.fail(self._formatMessage(msg, standardMsg)) 943 944 def assertIsNotNone(self, obj, msg=None): 945 """Included for symmetry with assertIsNone.""" 946 if obj is None: 947 standardMsg = 'unexpectedly None' 948 self.fail(self._formatMessage(msg, standardMsg)) 949 950 def assertRaisesRegexp(self, expected_exception, expected_regexp, 951 callable_obj=None, *args, **kwargs): 952 """Asserts that the message in a raised exception matches a regexp. 953 954 Args: 955 expected_exception: Exception class expected to be raised. 956 expected_regexp: Regexp (re pattern object or string) expected 957 to be found in error message. 958 callable_obj: Function to be called. 959 args: Extra args. 960 kwargs: Extra kwargs. 961 """ 962 context = _AssertRaisesContext(expected_exception, self, expected_regexp) 963 if callable_obj is None: 964 return context 965 # XXX (garrcoop): See comment above about `with context'. 966 context.__enter__() 967 try: 968 callable_obj(*args, **kwargs) 969 finally: 970 context.__exit__() 971 972 def assertRegexpMatches(self, text, expected_regex, msg=None): 973 if isinstance(expected_regex, basestring): 974 expected_regex = re.compile(expected_regex) 975 if not expected_regex.search(text): 976 msg = msg or "Regexp didn't match" 977 msg = '%s: %r not found in %r' % (msg, expected_regex.pattern, text) 978 raise self.failureException(msg) 979 980 981def _SortedListDifference(expected, actual): 982 """Finds elements in only one or the other of two, sorted input lists. 983 984 Returns a two-element tuple of lists. The first list contains those 985 elements in the "expected" list but not in the "actual" list, and the 986 second contains those elements in the "actual" list but not in the 987 "expected" list. Duplicate elements in either input list are ignored. 988 """ 989 i = j = 0 990 missing = [] 991 unexpected = [] 992 while True: 993 try: 994 e = expected[i] 995 a = actual[j] 996 if e < a: 997 missing.append(e) 998 i += 1 999 while expected[i] == e: 1000 i += 1 1001 elif e > a: 1002 unexpected.append(a) 1003 j += 1 1004 while actual[j] == a: 1005 j += 1 1006 else: 1007 i += 1 1008 try: 1009 while expected[i] == e: 1010 i += 1 1011 finally: 1012 j += 1 1013 while actual[j] == a: 1014 j += 1 1015 except IndexError: 1016 missing.extend(expected[i:]) 1017 unexpected.extend(actual[j:]) 1018 break 1019 return missing, unexpected 1020 1021 1022class TestSuite(object): 1023 """A test suite is a composite test consisting of a number of TestCases. 1024 1025 For use, create an instance of TestSuite, then add test case instances. 1026 When all tests have been added, the suite can be passed to a test 1027 runner, such as TextTestRunner. It will run the individual test cases 1028 in the order in which they were added, aggregating the results. When 1029 subclassing, do not forget to call the base class constructor. 1030 """ 1031 def __init__(self, tests=()): 1032 self._tests = [] 1033 self.addTests(tests) 1034 1035 def __repr__(self): 1036 return "<%s tests=%s>" % (_strclass(self.__class__), list(self)) 1037 1038 def __eq__(self, other): 1039 if not isinstance(other, self.__class__): 1040 return NotImplemented 1041 return self._tests == other._tests 1042 1043 def __ne__(self, other): 1044 return not self == other 1045 1046 # Can't guarantee hash invariant, so flag as unhashable 1047 __hash__ = None 1048 1049 def __iter__(self): 1050 return iter(self._tests) 1051 1052 def countTestCases(self): 1053 cases = 0 1054 for test in self: 1055 cases += test.countTestCases() 1056 return cases 1057 1058 def addTest(self, test): 1059 # sanity checks 1060 if not hasattr(test, '__call__'): 1061 raise TypeError("the test to add must be callable") 1062 if isinstance(test, type) and issubclass(test, (TestCase, TestSuite)): 1063 raise TypeError("TestCases and TestSuites must be instantiated " 1064 "before passing them to addTest()") 1065 self._tests.append(test) 1066 1067 def addTests(self, tests): 1068 if isinstance(tests, basestring): 1069 raise TypeError("tests must be an iterable of tests, not a string") 1070 for test in tests: 1071 self.addTest(test) 1072 1073 def run(self, result): 1074 for test in self: 1075 if result.shouldStop: 1076 break 1077 test(result) 1078 return result 1079 1080 def __call__(self, *args, **kwds): 1081 return self.run(*args, **kwds) 1082 1083 def debug(self): 1084 """Run the tests without collecting errors in a TestResult""" 1085 for test in self: 1086 test.debug() 1087 1088 1089class ClassTestSuite(TestSuite): 1090 """ 1091 Suite of tests derived from a single TestCase class. 1092 """ 1093 1094 def __init__(self, tests, class_collected_from): 1095 super(ClassTestSuite, self).__init__(tests) 1096 self.collected_from = class_collected_from 1097 1098 def id(self): 1099 module = getattr(self.collected_from, "__module__", None) 1100 if module is not None: 1101 return "%s.%s" % (str(module), str(self.collected_from.__name__)) 1102 return self.collected_from.__name__ 1103 1104 def run(self, result): 1105 if getattr(self.collected_from, "__unittest_skip__", False): 1106 # ClassTestSuite result pretends to be a TestCase enough to be 1107 # reported. 1108 result.startTest(self) 1109 try: 1110 result.addSkip(self, self.collected_from.__unittest_skip_why__) 1111 finally: 1112 result.stopTest(self) 1113 else: 1114 result = super(ClassTestSuite, self).run(result) 1115 return result 1116 1117 shortDescription = id 1118 1119 1120class FunctionTestCase(TestCase): 1121 """A test case that wraps a test function. 1122 1123 This is useful for slipping pre-existing test functions into the 1124 unittest framework. Optionally, set-up and tidy-up functions can be 1125 supplied. As with TestCase, the tidy-up ('tearDown') function will 1126 always be called if the set-up ('setUp') function ran successfully. 1127 """ 1128 1129 def __init__(self, testFunc, setUp=None, tearDown=None, description=None): 1130 super(FunctionTestCase, self).__init__() 1131 self._setUpFunc = setUp 1132 self._tearDownFunc = tearDown 1133 self._testFunc = testFunc 1134 self._description = description 1135 1136 def setUp(self): 1137 if self._setUpFunc is not None: 1138 self._setUpFunc() 1139 1140 def tearDown(self): 1141 if self._tearDownFunc is not None: 1142 self._tearDownFunc() 1143 1144 def runTest(self): 1145 self._testFunc() 1146 1147 def id(self): 1148 return self._testFunc.__name__ 1149 1150 def __eq__(self, other): 1151 if not isinstance(other, self.__class__): 1152 return NotImplemented 1153 1154 return self._setUpFunc == other._setUpFunc and \ 1155 self._tearDownFunc == other._tearDownFunc and \ 1156 self._testFunc == other._testFunc and \ 1157 self._description == other._description 1158 1159 def __ne__(self, other): 1160 return not self == other 1161 1162 def __hash__(self): 1163 return hash((type(self), self._setUpFunc, self._tearDownFunc, 1164 self._testFunc, self._description)) 1165 1166 def __str__(self): 1167 return "%s (%s)" % (_strclass(self.__class__), self._testFunc.__name__) 1168 1169 def __repr__(self): 1170 return "<%s testFunc=%s>" % (_strclass(self.__class__), self._testFunc) 1171 1172 def shortDescription(self): 1173 if self._description is not None: 1174 return self._description 1175 doc = self._testFunc.__doc__ 1176 return doc and doc.split("\n")[0].strip() or None 1177 1178 1179 1180############################################################################## 1181# Locating and loading tests 1182############################################################################## 1183 1184class TestLoader(object): 1185 """ 1186 This class is responsible for loading tests according to various criteria 1187 and returning them wrapped in a TestSuite 1188 """ 1189 testMethodPrefix = 'test' 1190 sortTestMethodsUsing = cmp 1191 suiteClass = TestSuite 1192 classSuiteClass = ClassTestSuite 1193 1194 def loadTestsFromTestCase(self, testCaseClass): 1195 """Return a suite of all tests cases contained in testCaseClass""" 1196 if issubclass(testCaseClass, TestSuite): 1197 raise TypeError("Test cases should not be derived from TestSuite." \ 1198 " Maybe you meant to derive from TestCase?") 1199 testCaseNames = self.getTestCaseNames(testCaseClass) 1200 if not testCaseNames and hasattr(testCaseClass, 'runTest'): 1201 testCaseNames = ['runTest'] 1202 suite = self.classSuiteClass(map(testCaseClass, testCaseNames), 1203 testCaseClass) 1204 return suite 1205 1206 def loadTestsFromModule(self, module): 1207 """Return a suite of all tests cases contained in the given module""" 1208 tests = [] 1209 for name in dir(module): 1210 obj = getattr(module, name) 1211 if isinstance(obj, type) and issubclass(obj, TestCase): 1212 tests.append(self.loadTestsFromTestCase(obj)) 1213 return self.suiteClass(tests) 1214 1215 def loadTestsFromName(self, name, module=None): 1216 """Return a suite of all tests cases given a string specifier. 1217 1218 The name may resolve either to a module, a test case class, a 1219 test method within a test case class, or a callable object which 1220 returns a TestCase or TestSuite instance. 1221 1222 The method optionally resolves the names relative to a given module. 1223 """ 1224 parts = name.split('.') 1225 if module is None: 1226 parts_copy = parts[:] 1227 while parts_copy: 1228 try: 1229 module = __import__('.'.join(parts_copy)) 1230 break 1231 except ImportError: 1232 del parts_copy[-1] 1233 if not parts_copy: 1234 raise 1235 parts = parts[1:] 1236 obj = module 1237 for part in parts: 1238 parent, obj = obj, getattr(obj, part) 1239 1240 if isinstance(obj, types.ModuleType): 1241 return self.loadTestsFromModule(obj) 1242 elif isinstance(obj, type) and issubclass(obj, TestCase): 1243 return self.loadTestsFromTestCase(obj) 1244 elif (isinstance(obj, types.UnboundMethodType) and 1245 isinstance(parent, type) and 1246 issubclass(parent, TestCase)): 1247 return TestSuite([parent(obj.__name__)]) 1248 elif isinstance(obj, TestSuite): 1249 return obj 1250 elif hasattr(obj, '__call__'): 1251 test = obj() 1252 if isinstance(test, TestSuite): 1253 return test 1254 elif isinstance(test, TestCase): 1255 return TestSuite([test]) 1256 else: 1257 raise TypeError("calling %s returned %s, not a test" % 1258 (obj, test)) 1259 else: 1260 raise TypeError("don't know how to make test from: %s" % obj) 1261 1262 def loadTestsFromNames(self, names, module=None): 1263 """Return a suite of all tests cases found using the given sequence 1264 of string specifiers. See 'loadTestsFromName()'. 1265 """ 1266 suites = [self.loadTestsFromName(name, module) for name in names] 1267 return self.suiteClass(suites) 1268 1269 def getTestCaseNames(self, testCaseClass): 1270 """Return a sorted sequence of method names found within testCaseClass 1271 """ 1272 def isTestMethod(attrname, testCaseClass=testCaseClass, 1273 prefix=self.testMethodPrefix): 1274 return attrname.startswith(prefix) and \ 1275 hasattr(getattr(testCaseClass, attrname), '__call__') 1276 testFnNames = filter(isTestMethod, dir(testCaseClass)) 1277 if self.sortTestMethodsUsing: 1278 testFnNames.sort(key=_CmpToKey(self.sortTestMethodsUsing)) 1279 return testFnNames 1280 1281 1282 1283defaultTestLoader = TestLoader() 1284 1285 1286############################################################################## 1287# Patches for old functions: these functions should be considered obsolete 1288############################################################################## 1289 1290def _makeLoader(prefix, sortUsing, suiteClass=None): 1291 loader = TestLoader() 1292 loader.sortTestMethodsUsing = sortUsing 1293 loader.testMethodPrefix = prefix 1294 if suiteClass: loader.suiteClass = suiteClass 1295 return loader 1296 1297def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp): 1298 return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass) 1299 1300def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite): 1301 return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass) 1302 1303def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite): 1304 return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module) 1305 1306 1307############################################################################## 1308# Text UI 1309############################################################################## 1310 1311class _WritelnDecorator(object): 1312 """Used to decorate file-like objects with a handy 'writeln' method""" 1313 def __init__(self,stream): 1314 self.stream = stream 1315 1316 def __getattr__(self, attr): 1317 return getattr(self.stream,attr) 1318 1319 def writeln(self, arg=None): 1320 if arg: 1321 self.write(arg) 1322 self.write('\n') # text-mode streams translate to \r\n if needed 1323 1324 1325class _TextTestResult(TestResult): 1326 """A test result class that can print formatted text results to a stream. 1327 1328 Used by TextTestRunner. 1329 """ 1330 separator1 = '=' * 70 1331 separator2 = '-' * 70 1332 1333 def __init__(self, stream, descriptions, verbosity): 1334 super(_TextTestResult, self).__init__() 1335 self.stream = stream 1336 self.showAll = verbosity > 1 1337 self.dots = verbosity == 1 1338 self.descriptions = descriptions 1339 1340 def getDescription(self, test): 1341 if self.descriptions: 1342 return test.shortDescription() or str(test) 1343 else: 1344 return str(test) 1345 1346 def startTest(self, test): 1347 super(_TextTestResult, self).startTest(test) 1348 if self.showAll: 1349 self.stream.write(self.getDescription(test)) 1350 self.stream.write(" ... ") 1351 self.stream.flush() 1352 1353 def addSuccess(self, test): 1354 super(_TextTestResult, self).addSuccess(test) 1355 if self.showAll: 1356 self.stream.writeln("ok") 1357 elif self.dots: 1358 self.stream.write('.') 1359 self.stream.flush() 1360 1361 def addError(self, test, err): 1362 super(_TextTestResult, self).addError(test, err) 1363 if self.showAll: 1364 self.stream.writeln("ERROR") 1365 elif self.dots: 1366 self.stream.write('E') 1367 self.stream.flush() 1368 1369 def addFailure(self, test, err): 1370 super(_TextTestResult, self).addFailure(test, err) 1371 if self.showAll: 1372 self.stream.writeln("FAIL") 1373 elif self.dots: 1374 self.stream.write('F') 1375 self.stream.flush() 1376 1377 def addSkip(self, test, reason): 1378 super(_TextTestResult, self).addSkip(test, reason) 1379 if self.showAll: 1380 self.stream.writeln("skipped '%s'" % str(reason)) 1381 elif self.dots: 1382 self.stream.write("s") 1383 self.stream.flush() 1384 1385 def addExpectedFailure(self, test, err): 1386 super(_TextTestResult, self).addExpectedFailure(test, err) 1387 if self.showAll: 1388 self.stream.writeln("expected failure") 1389 elif self.dots: 1390 self.stream.write("x") 1391 self.stream.flush() 1392 1393 def addUnexpectedSuccess(self, test): 1394 super(_TextTestResult, self).addUnexpectedSuccess(test) 1395 if self.showAll: 1396 self.stream.writeln("unexpected success") 1397 elif self.dots: 1398 self.stream.write("u") 1399 self.stream.flush() 1400 1401 def printErrors(self): 1402 if self.dots or self.showAll: 1403 self.stream.writeln() 1404 self.printErrorList('ERROR', self.errors) 1405 self.printErrorList('FAIL', self.failures) 1406 1407 def printErrorList(self, flavour, errors): 1408 for test, err in errors: 1409 self.stream.writeln(self.separator1) 1410 self.stream.writeln("%s: %s" % (flavour,self.getDescription(test))) 1411 self.stream.writeln(self.separator2) 1412 self.stream.writeln("%s" % err) 1413 1414 1415class TextTestRunner(object): 1416 """A test runner class that displays results in textual form. 1417 1418 It prints out the names of tests as they are run, errors as they 1419 occur, and a summary of the results at the end of the test run. 1420 """ 1421 def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1): 1422 self.stream = _WritelnDecorator(stream) 1423 self.descriptions = descriptions 1424 self.verbosity = verbosity 1425 1426 def _makeResult(self): 1427 return _TextTestResult(self.stream, self.descriptions, self.verbosity) 1428 1429 def run(self, test): 1430 "Run the given test case or test suite." 1431 result = self._makeResult() 1432 startTime = time.time() 1433 test(result) 1434 stopTime = time.time() 1435 timeTaken = stopTime - startTime 1436 result.printErrors() 1437 self.stream.writeln(result.separator2) 1438 run = result.testsRun 1439 self.stream.writeln("Ran %d test%s in %.3fs" % 1440 (run, run != 1 and "s" or "", timeTaken)) 1441 self.stream.writeln() 1442 results = map(len, (result.expectedFailures, 1443 result.unexpectedSuccesses, 1444 result.skipped)) 1445 expectedFails, unexpectedSuccesses, skipped = results 1446 infos = [] 1447 if not result.wasSuccessful(): 1448 self.stream.write("FAILED") 1449 failed, errored = map(len, (result.failures, result.errors)) 1450 if failed: 1451 infos.append("failures=%d" % failed) 1452 if errored: 1453 infos.append("errors=%d" % errored) 1454 else: 1455 self.stream.write("OK") 1456 if skipped: 1457 infos.append("skipped=%d" % skipped) 1458 if expectedFails: 1459 infos.append("expected failures=%d" % expectedFails) 1460 if unexpectedSuccesses: 1461 infos.append("unexpected successes=%d" % unexpectedSuccesses) 1462 if infos: 1463 self.stream.writeln(" (%s)" % (", ".join(infos),)) 1464 else: 1465 self.stream.write("\n") 1466 return result 1467 1468 1469 1470############################################################################## 1471# Facilities for running tests from the command line 1472############################################################################## 1473 1474class TestProgram(object): 1475 """A command-line program that runs a set of tests; this is primarily 1476 for making test modules conveniently executable. 1477 """ 1478 USAGE = """\ 1479Usage: %(progName)s [options] [test] [...] 1480 1481Options: 1482 -h, --help Show this message 1483 -v, --verbose Verbose output 1484 -q, --quiet Minimal output 1485 1486Examples: 1487 %(progName)s - run default set of tests 1488 %(progName)s MyTestSuite - run suite 'MyTestSuite' 1489 %(progName)s MyTestCase.testSomething - run MyTestCase.testSomething 1490 %(progName)s MyTestCase - run all 'test*' test methods 1491 in MyTestCase 1492""" 1493 def __init__(self, module='__main__', defaultTest=None, 1494 argv=None, testRunner=TextTestRunner, 1495 testLoader=defaultTestLoader): 1496 if isinstance(module, basestring): 1497 self.module = __import__(module) 1498 for part in module.split('.')[1:]: 1499 self.module = getattr(self.module, part) 1500 else: 1501 self.module = module 1502 if argv is None: 1503 argv = sys.argv 1504 self.verbosity = 1 1505 self.defaultTest = defaultTest 1506 self.testRunner = testRunner 1507 self.testLoader = testLoader 1508 self.progName = os.path.basename(argv[0]) 1509 self.parseArgs(argv) 1510 self.runTests() 1511 1512 def usageExit(self, msg=None): 1513 if msg: 1514 print msg 1515 print self.USAGE % self.__dict__ 1516 sys.exit(2) 1517 1518 def parseArgs(self, argv): 1519 import getopt 1520 long_opts = ['help','verbose','quiet'] 1521 try: 1522 options, args = getopt.getopt(argv[1:], 'hHvq', long_opts) 1523 for opt, value in options: 1524 if opt in ('-h','-H','--help'): 1525 self.usageExit() 1526 if opt in ('-q','--quiet'): 1527 self.verbosity = 0 1528 if opt in ('-v','--verbose'): 1529 self.verbosity = 2 1530 if len(args) == 0 and self.defaultTest is None: 1531 self.test = self.testLoader.loadTestsFromModule(self.module) 1532 return 1533 if len(args) > 0: 1534 self.testNames = args 1535 else: 1536 self.testNames = (self.defaultTest,) 1537 self.createTests() 1538 except getopt.error, msg: 1539 self.usageExit(msg) 1540 1541 def createTests(self): 1542 self.test = self.testLoader.loadTestsFromNames(self.testNames, 1543 self.module) 1544 1545 def runTests(self): 1546 if isinstance(self.testRunner, (type, types.ClassType)): 1547 try: 1548 testRunner = self.testRunner(verbosity=self.verbosity) 1549 except TypeError: 1550 # didn't accept the verbosity argument 1551 testRunner = self.testRunner() 1552 else: 1553 # it is assumed to be a TestRunner instance 1554 testRunner = self.testRunner 1555 result = testRunner.run(self.test) 1556 sys.exit(not result.wasSuccessful()) 1557 1558main = TestProgram 1559 1560 1561############################################################################## 1562# Executing this module from the command line 1563############################################################################## 1564 1565if __name__ == "__main__": 1566 main(module=None) 1567