| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | #!/usr/bin/env python | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | '''
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's | 
					
						
							|  |  |  | Smalltalk testing framework. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This module contains the core framework classes that form the basis of | 
					
						
							|  |  |  | specific test cases and suites (TestCase, TestSuite etc.), and also a | 
					
						
							|  |  |  | text-based utility class for running the tests and reporting the results | 
					
						
							| 
									
										
										
										
											2001-10-22 18:14:15 +00:00
										 |  |  |  (TextTestRunner). | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | Simple usage: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     import unittest | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class IntegerArithmenticTestCase(unittest.TestCase): | 
					
						
							|  |  |  |         def testAdd(self):  ## test method names begin 'test*' | 
					
						
							|  |  |  |             self.assertEquals((1 + 2), 3) | 
					
						
							|  |  |  |             self.assertEquals(0 + 1, 1) | 
					
						
							| 
									
										
										
										
											2001-09-06 08:24:40 +00:00
										 |  |  |         def testMultiply(self): | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |             self.assertEquals((0 * 10), 0) | 
					
						
							|  |  |  |             self.assertEquals((5 * 8), 40) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if __name__ == '__main__': | 
					
						
							|  |  |  |         unittest.main() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Further information is available in the bundled documentation, and from | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   http://pyunit.sourceforge.net/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | Copyright (c) 1999, 2000, 2001 Steve Purcell | 
					
						
							|  |  |  | This module is free software, and you may redistribute it and/or modify | 
					
						
							|  |  |  | it under the same terms as Python itself, so long as this copyright message | 
					
						
							|  |  |  | and disclaimer are retained in their original form. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | 
					
						
							|  |  |  | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF | 
					
						
							|  |  |  | THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | 
					
						
							|  |  |  | DAMAGE. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT | 
					
						
							|  |  |  | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | 
					
						
							|  |  |  | PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, | 
					
						
							|  |  |  | AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, | 
					
						
							|  |  |  | SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | '''
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | __author__ = "Steve Purcell" | 
					
						
							|  |  |  | __email__ = "stephen_purcell at yahoo dot com" | 
					
						
							| 
									
										
										
										
											2002-08-09 09:46:23 +00:00
										 |  |  | __version__ = "#Revision: 1.46 $"[11:-2] | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | import time | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import traceback | 
					
						
							|  |  |  | import string | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | import types | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ############################################################################## | 
					
						
							|  |  |  | # Test framework core | 
					
						
							|  |  |  | ############################################################################## | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-08 13:38:02 +00:00
										 |  |  | # All classes defined herein are 'new-style' classes, allowing use of 'super()' | 
					
						
							|  |  |  | __metaclass__ = type | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-09 09:46:23 +00:00
										 |  |  | def _strclass(cls): | 
					
						
							|  |  |  |     return "%s.%s" % (cls.__module__, cls.__name__) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | class TestResult: | 
					
						
							|  |  |  |     """Holder for test result information.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Test results are automatically managed by the TestCase and TestSuite | 
					
						
							|  |  |  |     classes, and do not need to be explicitly manipulated by writers of tests. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Each instance holds the total number of tests run, and collections of | 
					
						
							|  |  |  |     failures and errors that occurred among those test runs. The collections | 
					
						
							| 
									
										
										
										
											2001-09-06 08:24:40 +00:00
										 |  |  |     contain tuples of (testcase, exceptioninfo), where exceptioninfo is the | 
					
						
							| 
									
										
										
										
											2001-09-06 19:13:14 +00:00
										 |  |  |     formatted traceback of the error that occurred. | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.failures = [] | 
					
						
							|  |  |  |         self.errors = [] | 
					
						
							|  |  |  |         self.testsRun = 0 | 
					
						
							|  |  |  |         self.shouldStop = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def startTest(self, test): | 
					
						
							|  |  |  |         "Called when the given test is about to be run" | 
					
						
							|  |  |  |         self.testsRun = self.testsRun + 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def stopTest(self, test): | 
					
						
							|  |  |  |         "Called when the given test has been run" | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def addError(self, test, err): | 
					
						
							| 
									
										
										
										
											2001-09-06 08:24:40 +00:00
										 |  |  |         """Called when an error has occurred. 'err' is a tuple of values as
 | 
					
						
							|  |  |  |         returned by sys.exc_info(). | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         self.errors.append((test, self._exc_info_to_string(err))) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def addFailure(self, test, err): | 
					
						
							| 
									
										
										
										
											2001-09-06 08:24:40 +00:00
										 |  |  |         """Called when an error has occurred. 'err' is a tuple of values as
 | 
					
						
							|  |  |  |         returned by sys.exc_info()."""
 | 
					
						
							|  |  |  |         self.failures.append((test, self._exc_info_to_string(err))) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |     def addSuccess(self, test): | 
					
						
							|  |  |  |         "Called when a test has completed successfully" | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |     def wasSuccessful(self): | 
					
						
							|  |  |  |         "Tells whether or not this result was a success" | 
					
						
							|  |  |  |         return len(self.failures) == len(self.errors) == 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def stop(self): | 
					
						
							|  |  |  |         "Indicates that the tests should be aborted" | 
					
						
							|  |  |  |         self.shouldStop = 1 | 
					
						
							| 
									
										
										
										
											2001-03-29 04:36:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-06 08:24:40 +00:00
										 |  |  |     def _exc_info_to_string(self, err): | 
					
						
							|  |  |  |         """Converts a sys.exc_info()-style tuple of values into a string.""" | 
					
						
							|  |  |  |         return string.join(apply(traceback.format_exception, err), '') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         return "<%s run=%i errors=%i failures=%i>" % \ | 
					
						
							| 
									
										
										
										
											2002-08-09 09:46:23 +00:00
										 |  |  |                (_strclass(self.__class__), self.testsRun, len(self.errors), | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |                 len(self.failures)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestCase: | 
					
						
							|  |  |  |     """A class whose instances are single test cases.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     By default, the test code itself should be placed in a method named | 
					
						
							|  |  |  |     'runTest'. | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-29 04:36:09 +00:00
										 |  |  |     If the fixture may be used for many test cases, create as | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |     many test methods as are needed. When instantiating such a TestCase | 
					
						
							|  |  |  |     subclass, specify in the constructor arguments the name of the test method | 
					
						
							|  |  |  |     that the instance is to execute. | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-29 04:36:09 +00:00
										 |  |  |     Test authors should subclass TestCase for their own tests. Construction | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |     and deconstruction of the test's environment ('fixture') can be | 
					
						
							|  |  |  |     implemented by overriding the 'setUp' and 'tearDown' methods respectively. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If it is necessary to override the __init__ method, the base class | 
					
						
							|  |  |  |     __init__ method must always be called. It is important that subclasses | 
					
						
							|  |  |  |     should not change the signature of their __init__ method, since instances | 
					
						
							|  |  |  |     of the classes are instantiated automatically by parts of the framework | 
					
						
							|  |  |  |     in order to be run. | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # This attribute determines which exception will be raised when | 
					
						
							|  |  |  |     # the instance's assertion methods fail; test methods raising this | 
					
						
							|  |  |  |     # exception will be deemed to have 'failed' rather than 'errored' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     failureException = AssertionError | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |     def __init__(self, methodName='runTest'): | 
					
						
							|  |  |  |         """Create an instance of the class that will use the named test
 | 
					
						
							|  |  |  |            method when executed. Raises a ValueError if the instance does | 
					
						
							|  |  |  |            not have a method with the specified name. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |             self.__testMethodName = methodName | 
					
						
							|  |  |  |             testMethod = getattr(self, methodName) | 
					
						
							|  |  |  |             self.__testMethodDoc = testMethod.__doc__ | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         except AttributeError: | 
					
						
							|  |  |  |             raise ValueError, "no such test method in %s: %s" % \ | 
					
						
							|  |  |  |                   (self.__class__, methodName) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setUp(self): | 
					
						
							|  |  |  |         "Hook method for setting up the test fixture before exercising it." | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def tearDown(self): | 
					
						
							|  |  |  |         "Hook method for deconstructing the test fixture after testing it." | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def countTestCases(self): | 
					
						
							|  |  |  |         return 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def defaultTestResult(self): | 
					
						
							|  |  |  |         return TestResult() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def shortDescription(self): | 
					
						
							|  |  |  |         """Returns a one-line description of the test, or None if no
 | 
					
						
							|  |  |  |         description has been provided. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         The default implementation of this method returns the first line of | 
					
						
							|  |  |  |         the specified test method's docstring. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         doc = self.__testMethodDoc | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         return doc and string.strip(string.split(doc, "\n")[0]) or None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def id(self): | 
					
						
							| 
									
										
										
										
											2002-08-09 09:46:23 +00:00
										 |  |  |         return "%s.%s" % (_strclass(self.__class__), self.__testMethodName) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __str__(self): | 
					
						
							| 
									
										
										
										
											2002-08-13 20:43:46 +00:00
										 |  |  |         return "%s (%s)" % (self.__testMethodName, _strclass(self.__class__)) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         return "<%s testMethod=%s>" % \ | 
					
						
							| 
									
										
										
										
											2002-08-09 09:46:23 +00:00
										 |  |  |                (_strclass(self.__class__), self.__testMethodName) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def run(self, result=None): | 
					
						
							|  |  |  |         return self(result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __call__(self, result=None): | 
					
						
							|  |  |  |         if result is None: result = self.defaultTestResult() | 
					
						
							|  |  |  |         result.startTest(self) | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         testMethod = getattr(self, self.__testMethodName) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 self.setUp() | 
					
						
							| 
									
										
										
										
											2001-12-07 03:39:34 +00:00
										 |  |  |             except KeyboardInterrupt: | 
					
						
							|  |  |  |                 raise | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |             except: | 
					
						
							| 
									
										
										
										
											2001-10-22 18:14:15 +00:00
										 |  |  |                 result.addError(self, self.__exc_info()) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |                 return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |             ok = 0 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |             try: | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |                 testMethod() | 
					
						
							|  |  |  |                 ok = 1 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |             except self.failureException, e: | 
					
						
							| 
									
										
										
										
											2001-10-22 18:14:15 +00:00
										 |  |  |                 result.addFailure(self, self.__exc_info()) | 
					
						
							| 
									
										
										
										
											2001-12-07 03:39:34 +00:00
										 |  |  |             except KeyboardInterrupt: | 
					
						
							|  |  |  |                 raise | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |             except: | 
					
						
							| 
									
										
										
										
											2001-10-22 18:14:15 +00:00
										 |  |  |                 result.addError(self, self.__exc_info()) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 self.tearDown() | 
					
						
							| 
									
										
										
										
											2001-12-07 03:39:34 +00:00
										 |  |  |             except KeyboardInterrupt: | 
					
						
							|  |  |  |                 raise | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |             except: | 
					
						
							| 
									
										
										
										
											2001-10-22 18:14:15 +00:00
										 |  |  |                 result.addError(self, self.__exc_info()) | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |                 ok = 0 | 
					
						
							|  |  |  |             if ok: result.addSuccess(self) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         finally: | 
					
						
							|  |  |  |             result.stopTest(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def debug(self): | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         """Run the test without collecting errors in a TestResult""" | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         self.setUp() | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         getattr(self, self.__testMethodName)() | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         self.tearDown() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |     def __exc_info(self): | 
					
						
							|  |  |  |         """Return a version of sys.exc_info() with the traceback frame
 | 
					
						
							|  |  |  |            minimised; usually the top level of the traceback frame is not | 
					
						
							|  |  |  |            needed. | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |         exctype, excvalue, tb = sys.exc_info() | 
					
						
							|  |  |  |         if sys.platform[:4] == 'java': ## tracebacks look different in Jython | 
					
						
							|  |  |  |             return (exctype, excvalue, tb) | 
					
						
							|  |  |  |         newtb = tb.tb_next | 
					
						
							|  |  |  |         if newtb is None: | 
					
						
							|  |  |  |             return (exctype, excvalue, tb) | 
					
						
							|  |  |  |         return (exctype, excvalue, newtb) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |     def fail(self, msg=None): | 
					
						
							|  |  |  |         """Fail immediately, with the given message.""" | 
					
						
							|  |  |  |         raise self.failureException, msg | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def failIf(self, expr, msg=None): | 
					
						
							|  |  |  |         "Fail the test if the expression is true." | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |         if expr: raise self.failureException, msg | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def failUnless(self, expr, msg=None): | 
					
						
							|  |  |  |         """Fail the test unless the expression is true.""" | 
					
						
							|  |  |  |         if not expr: raise self.failureException, msg | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |     def failUnlessRaises(self, excClass, callableObj, *args, **kwargs): | 
					
						
							|  |  |  |         """Fail unless an exception of class excClass is thrown
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |            by callableObj when invoked with arguments args and keyword | 
					
						
							|  |  |  |            arguments kwargs. If a different type of exception is | 
					
						
							|  |  |  |            thrown, it will not be caught, and the test case will be | 
					
						
							|  |  |  |            deemed to have suffered an error, exactly as for an | 
					
						
							|  |  |  |            unexpected exception. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             apply(callableObj, args, kwargs) | 
					
						
							|  |  |  |         except excClass: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             if hasattr(excClass,'__name__'): excName = excClass.__name__ | 
					
						
							|  |  |  |             else: excName = str(excClass) | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |             raise self.failureException, excName | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |     def failUnlessEqual(self, first, second, msg=None): | 
					
						
							|  |  |  |         """Fail if the two objects are unequal as determined by the '!='
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |            operator. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |         if first != second: | 
					
						
							| 
									
										
										
										
											2001-12-17 10:13:17 +00:00
										 |  |  |             raise self.failureException, \ | 
					
						
							|  |  |  |                   (msg or '%s != %s' % (`first`, `second`)) | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |     def failIfEqual(self, first, second, msg=None): | 
					
						
							|  |  |  |         """Fail if the two objects are equal as determined by the '=='
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |            operator. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |         if first == second: | 
					
						
							| 
									
										
										
										
											2001-12-17 10:13:17 +00:00
										 |  |  |             raise self.failureException, \ | 
					
						
							|  |  |  |                   (msg or '%s == %s' % (`first`, `second`)) | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |     assertEqual = assertEquals = failUnlessEqual | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |     assertNotEqual = assertNotEquals = failIfEqual | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assertRaises = failUnlessRaises | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert_ = failUnless | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class TestSuite: | 
					
						
							|  |  |  |     """A test suite is a composite test consisting of a number of TestCases.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For use, create an instance of TestSuite, then add test case instances. | 
					
						
							|  |  |  |     When all tests have been added, the suite can be passed to a test | 
					
						
							|  |  |  |     runner, such as TextTestRunner. It will run the individual test cases | 
					
						
							|  |  |  |     in the order in which they were added, aggregating the results. When | 
					
						
							|  |  |  |     subclassing, do not forget to call the base class constructor. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     def __init__(self, tests=()): | 
					
						
							|  |  |  |         self._tests = [] | 
					
						
							|  |  |  |         self.addTests(tests) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							| 
									
										
										
										
											2002-08-09 09:46:23 +00:00
										 |  |  |         return "<%s tests=%s>" % (_strclass(self.__class__), self._tests) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     __str__ = __repr__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def countTestCases(self): | 
					
						
							|  |  |  |         cases = 0 | 
					
						
							|  |  |  |         for test in self._tests: | 
					
						
							|  |  |  |             cases = cases + test.countTestCases() | 
					
						
							|  |  |  |         return cases | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def addTest(self, test): | 
					
						
							|  |  |  |         self._tests.append(test) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def addTests(self, tests): | 
					
						
							|  |  |  |         for test in tests: | 
					
						
							|  |  |  |             self.addTest(test) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def run(self, result): | 
					
						
							|  |  |  |         return self(result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __call__(self, result): | 
					
						
							|  |  |  |         for test in self._tests: | 
					
						
							|  |  |  |             if result.shouldStop: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             test(result) | 
					
						
							|  |  |  |         return result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def debug(self): | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         """Run the tests without collecting errors in a TestResult""" | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         for test in self._tests: test.debug() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FunctionTestCase(TestCase): | 
					
						
							|  |  |  |     """A test case that wraps a test function.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This is useful for slipping pre-existing test functions into the | 
					
						
							|  |  |  |     PyUnit framework. Optionally, set-up and tidy-up functions can be | 
					
						
							|  |  |  |     supplied. As with TestCase, the tidy-up ('tearDown') function will | 
					
						
							|  |  |  |     always be called if the set-up ('setUp') function ran successfully. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, testFunc, setUp=None, tearDown=None, | 
					
						
							|  |  |  |                  description=None): | 
					
						
							|  |  |  |         TestCase.__init__(self) | 
					
						
							|  |  |  |         self.__setUpFunc = setUp | 
					
						
							|  |  |  |         self.__tearDownFunc = tearDown | 
					
						
							|  |  |  |         self.__testFunc = testFunc | 
					
						
							|  |  |  |         self.__description = description | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setUp(self): | 
					
						
							|  |  |  |         if self.__setUpFunc is not None: | 
					
						
							|  |  |  |             self.__setUpFunc() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def tearDown(self): | 
					
						
							|  |  |  |         if self.__tearDownFunc is not None: | 
					
						
							|  |  |  |             self.__tearDownFunc() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def runTest(self): | 
					
						
							|  |  |  |         self.__testFunc() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def id(self): | 
					
						
							|  |  |  |         return self.__testFunc.__name__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __str__(self): | 
					
						
							| 
									
										
										
										
											2002-08-09 09:46:23 +00:00
										 |  |  |         return "%s (%s)" % (_strclass(self.__class__), self.__testFunc.__name__) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							| 
									
										
										
										
											2002-08-09 09:46:23 +00:00
										 |  |  |         return "<%s testFunc=%s>" % (_strclass(self.__class__), self.__testFunc) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def shortDescription(self): | 
					
						
							|  |  |  |         if self.__description is not None: return self.__description | 
					
						
							|  |  |  |         doc = self.__testFunc.__doc__ | 
					
						
							|  |  |  |         return doc and string.strip(string.split(doc, "\n")[0]) or None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ############################################################################## | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | # Locating and loading tests | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | ############################################################################## | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | class TestLoader: | 
					
						
							|  |  |  |     """This class is responsible for loading tests according to various
 | 
					
						
							|  |  |  |     criteria and returning them wrapped in a Test | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |     testMethodPrefix = 'test' | 
					
						
							|  |  |  |     sortTestMethodsUsing = cmp | 
					
						
							|  |  |  |     suiteClass = TestSuite | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |     def loadTestsFromTestCase(self, testCaseClass): | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |         """Return a suite of all tests cases contained in testCaseClass""" | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         return self.suiteClass(map(testCaseClass, | 
					
						
							|  |  |  |                                    self.getTestCaseNames(testCaseClass))) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |     def loadTestsFromModule(self, module): | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |         """Return a suite of all tests cases contained in the given module""" | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         tests = [] | 
					
						
							|  |  |  |         for name in dir(module): | 
					
						
							|  |  |  |             obj = getattr(module, name) | 
					
						
							|  |  |  |             if type(obj) == types.ClassType and issubclass(obj, TestCase): | 
					
						
							|  |  |  |                 tests.append(self.loadTestsFromTestCase(obj)) | 
					
						
							|  |  |  |         return self.suiteClass(tests) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def loadTestsFromName(self, name, module=None): | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |         """Return a suite of all tests cases given a string specifier.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         The name may resolve either to a module, a test case class, a | 
					
						
							|  |  |  |         test method within a test case class, or a callable object which | 
					
						
							|  |  |  |         returns a TestCase or TestSuite instance. | 
					
						
							| 
									
										
										
										
											2001-04-13 05:37:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |         The method optionally resolves the names relative to a given module. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         parts = string.split(name, '.') | 
					
						
							|  |  |  |         if module is None: | 
					
						
							|  |  |  |             if not parts: | 
					
						
							|  |  |  |                 raise ValueError, "incomplete test name: %s" % name | 
					
						
							|  |  |  |             else: | 
					
						
							| 
									
										
										
										
											2001-04-09 15:37:31 +00:00
										 |  |  |                 parts_copy = parts[:] | 
					
						
							|  |  |  |                 while parts_copy: | 
					
						
							|  |  |  |                     try: | 
					
						
							|  |  |  |                         module = __import__(string.join(parts_copy,'.')) | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |                     except ImportError: | 
					
						
							|  |  |  |                         del parts_copy[-1] | 
					
						
							|  |  |  |                         if not parts_copy: raise | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |                 parts = parts[1:] | 
					
						
							|  |  |  |         obj = module | 
					
						
							|  |  |  |         for part in parts: | 
					
						
							|  |  |  |             obj = getattr(obj, part) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 07:57:26 +00:00
										 |  |  |         import unittest | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         if type(obj) == types.ModuleType: | 
					
						
							|  |  |  |             return self.loadTestsFromModule(obj) | 
					
						
							| 
									
										
										
										
											2001-08-08 07:57:26 +00:00
										 |  |  |         elif type(obj) == types.ClassType and issubclass(obj, unittest.TestCase): | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |             return self.loadTestsFromTestCase(obj) | 
					
						
							|  |  |  |         elif type(obj) == types.UnboundMethodType: | 
					
						
							|  |  |  |             return obj.im_class(obj.__name__) | 
					
						
							|  |  |  |         elif callable(obj): | 
					
						
							|  |  |  |             test = obj() | 
					
						
							| 
									
										
										
										
											2001-08-08 07:57:26 +00:00
										 |  |  |             if not isinstance(test, unittest.TestCase) and \ | 
					
						
							|  |  |  |                not isinstance(test, unittest.TestSuite): | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |                 raise ValueError, \ | 
					
						
							| 
									
										
										
										
											2001-05-10 01:28:40 +00:00
										 |  |  |                       "calling %s returned %s, not a test" % (obj,test) | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |             return test | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             raise ValueError, "don't know how to make test from: %s" % obj | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |     def loadTestsFromNames(self, names, module=None): | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |         """Return a suite of all tests cases found using the given sequence
 | 
					
						
							|  |  |  |         of string specifiers. See 'loadTestsFromName()'. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         suites = [] | 
					
						
							|  |  |  |         for name in names: | 
					
						
							|  |  |  |             suites.append(self.loadTestsFromName(name, module)) | 
					
						
							|  |  |  |         return self.suiteClass(suites) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |     def getTestCaseNames(self, testCaseClass): | 
					
						
							| 
									
										
										
										
											2001-04-12 09:05:01 +00:00
										 |  |  |         """Return a sorted sequence of method names found within testCaseClass
 | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         testFnNames = filter(lambda n,p=self.testMethodPrefix: n[:len(p)] == p, | 
					
						
							|  |  |  |                              dir(testCaseClass)) | 
					
						
							|  |  |  |         for baseclass in testCaseClass.__bases__: | 
					
						
							|  |  |  |             for testFnName in self.getTestCaseNames(baseclass): | 
					
						
							|  |  |  |                 if testFnName not in testFnNames:  # handle overridden methods | 
					
						
							|  |  |  |                     testFnNames.append(testFnName) | 
					
						
							|  |  |  |         if self.sortTestMethodsUsing: | 
					
						
							|  |  |  |             testFnNames.sort(self.sortTestMethodsUsing) | 
					
						
							|  |  |  |         return testFnNames | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | defaultTestLoader = TestLoader() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ############################################################################## | 
					
						
							|  |  |  | # Patches for old functions: these functions should be considered obsolete | 
					
						
							|  |  |  | ############################################################################## | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _makeLoader(prefix, sortUsing, suiteClass=None): | 
					
						
							|  |  |  |     loader = TestLoader() | 
					
						
							|  |  |  |     loader.sortTestMethodsUsing = sortUsing | 
					
						
							|  |  |  |     loader.testMethodPrefix = prefix | 
					
						
							|  |  |  |     if suiteClass: loader.suiteClass = suiteClass | 
					
						
							|  |  |  |     return loader | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp): | 
					
						
							|  |  |  |     return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite): | 
					
						
							|  |  |  |     return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite): | 
					
						
							|  |  |  |     return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ############################################################################## | 
					
						
							|  |  |  | # Text UI | 
					
						
							|  |  |  | ############################################################################## | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _WritelnDecorator: | 
					
						
							|  |  |  |     """Used to decorate file-like objects with a handy 'writeln' method""" | 
					
						
							|  |  |  |     def __init__(self,stream): | 
					
						
							|  |  |  |         self.stream = stream | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __getattr__(self, attr): | 
					
						
							|  |  |  |         return getattr(self.stream,attr) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def writeln(self, *args): | 
					
						
							|  |  |  |         if args: apply(self.write, args) | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         self.write('\n') # text-mode streams translate to \r\n if needed | 
					
						
							| 
									
										
										
										
											2001-03-29 04:36:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | class _TextTestResult(TestResult): | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |     """A test result class that can print formatted text results to a stream.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |     Used by TextTestRunner. | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |     separator1 = '=' * 70 | 
					
						
							|  |  |  |     separator2 = '-' * 70 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, stream, descriptions, verbosity): | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         TestResult.__init__(self) | 
					
						
							|  |  |  |         self.stream = stream | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         self.showAll = verbosity > 1 | 
					
						
							|  |  |  |         self.dots = verbosity == 1 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         self.descriptions = descriptions | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def getDescription(self, test): | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         if self.descriptions: | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |             return test.shortDescription() or str(test) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |             return str(test) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |     def startTest(self, test): | 
					
						
							|  |  |  |         TestResult.startTest(self, test) | 
					
						
							|  |  |  |         if self.showAll: | 
					
						
							|  |  |  |             self.stream.write(self.getDescription(test)) | 
					
						
							|  |  |  |             self.stream.write(" ... ") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def addSuccess(self, test): | 
					
						
							|  |  |  |         TestResult.addSuccess(self, test) | 
					
						
							|  |  |  |         if self.showAll: | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |             self.stream.writeln("ok") | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         elif self.dots: | 
					
						
							|  |  |  |             self.stream.write('.') | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def addError(self, test, err): | 
					
						
							|  |  |  |         TestResult.addError(self, test, err) | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         if self.showAll: | 
					
						
							|  |  |  |             self.stream.writeln("ERROR") | 
					
						
							|  |  |  |         elif self.dots: | 
					
						
							|  |  |  |             self.stream.write('E') | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def addFailure(self, test, err): | 
					
						
							|  |  |  |         TestResult.addFailure(self, test, err) | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         if self.showAll: | 
					
						
							|  |  |  |             self.stream.writeln("FAIL") | 
					
						
							|  |  |  |         elif self.dots: | 
					
						
							|  |  |  |             self.stream.write('F') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def printErrors(self): | 
					
						
							|  |  |  |         if self.dots or self.showAll: | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |             self.stream.writeln() | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         self.printErrorList('ERROR', self.errors) | 
					
						
							|  |  |  |         self.printErrorList('FAIL', self.failures) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def printErrorList(self, flavour, errors): | 
					
						
							|  |  |  |         for test, err in errors: | 
					
						
							|  |  |  |             self.stream.writeln(self.separator1) | 
					
						
							|  |  |  |             self.stream.writeln("%s: %s" % (flavour,self.getDescription(test))) | 
					
						
							|  |  |  |             self.stream.writeln(self.separator2) | 
					
						
							| 
									
										
										
										
											2001-09-06 08:24:40 +00:00
										 |  |  |             self.stream.writeln("%s" % err) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | class TextTestRunner: | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |     """A test runner class that displays results in textual form.
 | 
					
						
							| 
									
										
										
										
											2001-03-29 04:36:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |     It prints out the names of tests as they are run, errors as they | 
					
						
							|  |  |  |     occur, and a summary of the results at the end of the test run. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |     def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1): | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         self.stream = _WritelnDecorator(stream) | 
					
						
							|  |  |  |         self.descriptions = descriptions | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         self.verbosity = verbosity | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _makeResult(self): | 
					
						
							|  |  |  |         return _TextTestResult(self.stream, self.descriptions, self.verbosity) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def run(self, test): | 
					
						
							|  |  |  |         "Run the given test case or test suite." | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         result = self._makeResult() | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         startTime = time.time() | 
					
						
							|  |  |  |         test(result) | 
					
						
							|  |  |  |         stopTime = time.time() | 
					
						
							|  |  |  |         timeTaken = float(stopTime - startTime) | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         result.printErrors() | 
					
						
							|  |  |  |         self.stream.writeln(result.separator2) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         run = result.testsRun | 
					
						
							|  |  |  |         self.stream.writeln("Ran %d test%s in %.3fs" % | 
					
						
							| 
									
										
										
										
											2002-05-31 14:15:11 +00:00
										 |  |  |                             (run, run != 1 and "s" or "", timeTaken)) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         self.stream.writeln() | 
					
						
							|  |  |  |         if not result.wasSuccessful(): | 
					
						
							|  |  |  |             self.stream.write("FAILED (") | 
					
						
							|  |  |  |             failed, errored = map(len, (result.failures, result.errors)) | 
					
						
							|  |  |  |             if failed: | 
					
						
							|  |  |  |                 self.stream.write("failures=%d" % failed) | 
					
						
							|  |  |  |             if errored: | 
					
						
							|  |  |  |                 if failed: self.stream.write(", ") | 
					
						
							|  |  |  |                 self.stream.write("errors=%d" % errored) | 
					
						
							|  |  |  |             self.stream.writeln(")") | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.stream.writeln("OK") | 
					
						
							|  |  |  |         return result | 
					
						
							| 
									
										
										
										
											2001-03-29 04:36:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ############################################################################## | 
					
						
							|  |  |  | # Facilities for running tests from the command line | 
					
						
							|  |  |  | ############################################################################## | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestProgram: | 
					
						
							|  |  |  |     """A command-line program that runs a set of tests; this is primarily
 | 
					
						
							|  |  |  |        for making test modules conveniently executable. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     USAGE = """\
 | 
					
						
							| 
									
										
										
										
											2001-04-09 15:37:31 +00:00
										 |  |  | Usage: %(progName)s [options] [test] [...] | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Options: | 
					
						
							|  |  |  |   -h, --help       Show this message | 
					
						
							|  |  |  |   -v, --verbose    Verbose output | 
					
						
							|  |  |  |   -q, --quiet      Minimal output | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Examples: | 
					
						
							|  |  |  |   %(progName)s                               - run default set of tests | 
					
						
							|  |  |  |   %(progName)s MyTestSuite                   - run suite 'MyTestSuite' | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |   %(progName)s MyTestCase.testSomething      - run MyTestCase.testSomething | 
					
						
							|  |  |  |   %(progName)s MyTestCase                    - run all 'test*' test methods | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |                                                in MyTestCase | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  |     def __init__(self, module='__main__', defaultTest=None, | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |                  argv=None, testRunner=None, testLoader=defaultTestLoader): | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         if type(module) == type(''): | 
					
						
							|  |  |  |             self.module = __import__(module) | 
					
						
							|  |  |  |             for part in string.split(module,'.')[1:]: | 
					
						
							|  |  |  |                 self.module = getattr(self.module, part) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.module = module | 
					
						
							|  |  |  |         if argv is None: | 
					
						
							|  |  |  |             argv = sys.argv | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         self.verbosity = 1 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         self.defaultTest = defaultTest | 
					
						
							|  |  |  |         self.testRunner = testRunner | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         self.testLoader = testLoader | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         self.progName = os.path.basename(argv[0]) | 
					
						
							|  |  |  |         self.parseArgs(argv) | 
					
						
							|  |  |  |         self.runTests() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def usageExit(self, msg=None): | 
					
						
							|  |  |  |         if msg: print msg | 
					
						
							|  |  |  |         print self.USAGE % self.__dict__ | 
					
						
							|  |  |  |         sys.exit(2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def parseArgs(self, argv): | 
					
						
							|  |  |  |         import getopt | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |             options, args = getopt.getopt(argv[1:], 'hHvq', | 
					
						
							|  |  |  |                                           ['help','verbose','quiet']) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |             for opt, value in options: | 
					
						
							|  |  |  |                 if opt in ('-h','-H','--help'): | 
					
						
							|  |  |  |                     self.usageExit() | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |                 if opt in ('-q','--quiet'): | 
					
						
							|  |  |  |                     self.verbosity = 0 | 
					
						
							|  |  |  |                 if opt in ('-v','--verbose'): | 
					
						
							|  |  |  |                     self.verbosity = 2 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |             if len(args) == 0 and self.defaultTest is None: | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |                 self.test = self.testLoader.loadTestsFromModule(self.module) | 
					
						
							|  |  |  |                 return | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |             if len(args) > 0: | 
					
						
							|  |  |  |                 self.testNames = args | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.testNames = (self.defaultTest,) | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |             self.createTests() | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         except getopt.error, msg: | 
					
						
							|  |  |  |             self.usageExit(msg) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def createTests(self): | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         self.test = self.testLoader.loadTestsFromNames(self.testNames, | 
					
						
							|  |  |  |                                                        self.module) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def runTests(self): | 
					
						
							|  |  |  |         if self.testRunner is None: | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |             self.testRunner = TextTestRunner(verbosity=self.verbosity) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  |         result = self.testRunner.run(self.test) | 
					
						
							| 
									
										
										
										
											2001-03-29 04:36:09 +00:00
										 |  |  |         sys.exit(not result.wasSuccessful()) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:09:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | main = TestProgram | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ############################################################################## | 
					
						
							|  |  |  | # Executing this module from the command line | 
					
						
							|  |  |  | ############################################################################## | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     main(module=None) |