PyXR

c:\python24\lib \ unittest.py



0001 #!/usr/bin/env python
0002 '''
0003 Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
0004 Smalltalk testing framework.
0005 
0006 This module contains the core framework classes that form the basis of
0007 specific test cases and suites (TestCase, TestSuite etc.), and also a
0008 text-based utility class for running the tests and reporting the results
0009  (TextTestRunner).
0010 
0011 Simple usage:
0012 
0013     import unittest
0014 
0015     class IntegerArithmenticTestCase(unittest.TestCase):
0016         def testAdd(self):  ## test method names begin 'test*'
0017             self.assertEquals((1 + 2), 3)
0018             self.assertEquals(0 + 1, 1)
0019         def testMultiply(self):
0020             self.assertEquals((0 * 10), 0)
0021             self.assertEquals((5 * 8), 40)
0022 
0023     if __name__ == '__main__':
0024         unittest.main()
0025 
0026 Further information is available in the bundled documentation, and from
0027 
0028   http://pyunit.sourceforge.net/
0029 
0030 Copyright (c) 1999-2003 Steve Purcell
0031 This module is free software, and you may redistribute it and/or modify
0032 it under the same terms as Python itself, so long as this copyright message
0033 and disclaimer are retained in their original form.
0034 
0035 IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
0036 SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
0037 THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
0038 DAMAGE.
0039 
0040 THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
0041 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
0042 PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
0043 AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
0044 SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
0045 '''
0046 
0047 __author__ = "Steve Purcell"
0048 __email__ = "stephen_purcell at yahoo dot com"
0049 __version__ = "#Revision: 1.63 $"[11:-2]
0050 
0051 import time
0052 import sys
0053 import traceback
0054 import os
0055 import types
0056 
0057 ##############################################################################
0058 # Exported classes and functions
0059 ##############################################################################
0060 __all__ = ['TestResult', 'TestCase', 'TestSuite', 'TextTestRunner',
0061            'TestLoader', 'FunctionTestCase', 'main', 'defaultTestLoader']
0062 
0063 # Expose obsolete functions for backwards compatibility
0064 __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
0065 
0066 
0067 ##############################################################################
0068 # Backward compatibility
0069 ##############################################################################
0070 if sys.version_info[:2] < (2, 2):
0071     False, True = 0, 1
0072     def isinstance(obj, clsinfo):
0073         import __builtin__
0074         if type(clsinfo) in (types.TupleType, types.ListType):
0075             for cls in clsinfo:
0076                 if cls is type: cls = types.ClassType
0077                 if __builtin__.isinstance(obj, cls):
0078                     return 1
0079             return 0
0080         else: return __builtin__.isinstance(obj, clsinfo)
0081 
0082 
0083 ##############################################################################
0084 # Test framework core
0085 ##############################################################################
0086 
0087 # All classes defined herein are 'new-style' classes, allowing use of 'super()'
0088 __metaclass__ = type
0089 
0090 def _strclass(cls):
0091     return "%s.%s" % (cls.__module__, cls.__name__)
0092 
0093 __unittest = 1
0094 
0095 class TestResult:
0096     """Holder for test result information.
0097 
0098     Test results are automatically managed by the TestCase and TestSuite
0099     classes, and do not need to be explicitly manipulated by writers of tests.
0100 
0101     Each instance holds the total number of tests run, and collections of
0102     failures and errors that occurred among those test runs. The collections
0103     contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
0104     formatted traceback of the error that occurred.
0105     """
0106     def __init__(self):
0107         self.failures = []
0108         self.errors = []
0109         self.testsRun = 0
0110         self.shouldStop = 0
0111 
0112     def startTest(self, test):
0113         "Called when the given test is about to be run"
0114         self.testsRun = self.testsRun + 1
0115 
0116     def stopTest(self, test):
0117         "Called when the given test has been run"
0118         pass
0119 
0120     def addError(self, test, err):
0121         """Called when an error has occurred. 'err' is a tuple of values as
0122         returned by sys.exc_info().
0123         """
0124         self.errors.append((test, self._exc_info_to_string(err, test)))
0125 
0126     def addFailure(self, test, err):
0127         """Called when an error has occurred. 'err' is a tuple of values as
0128         returned by sys.exc_info()."""
0129         self.failures.append((test, self._exc_info_to_string(err, test)))
0130 
0131     def addSuccess(self, test):
0132         "Called when a test has completed successfully"
0133         pass
0134 
0135     def wasSuccessful(self):
0136         "Tells whether or not this result was a success"
0137         return len(self.failures) == len(self.errors) == 0
0138 
0139     def stop(self):
0140         "Indicates that the tests should be aborted"
0141         self.shouldStop = True
0142 
0143     def _exc_info_to_string(self, err, test):
0144         """Converts a sys.exc_info()-style tuple of values into a string."""
0145         exctype, value, tb = err
0146         # Skip test runner traceback levels
0147         while tb and self._is_relevant_tb_level(tb):
0148             tb = tb.tb_next
0149         if exctype is test.failureException:
0150             # Skip assert*() traceback levels
0151             length = self._count_relevant_tb_levels(tb)
0152             return ''.join(traceback.format_exception(exctype, value, tb, length))
0153         return ''.join(traceback.format_exception(exctype, value, tb))
0154 
0155     def _is_relevant_tb_level(self, tb):
0156         return tb.tb_frame.f_globals.has_key('__unittest')
0157 
0158     def _count_relevant_tb_levels(self, tb):
0159         length = 0
0160         while tb and not self._is_relevant_tb_level(tb):
0161             length += 1
0162             tb = tb.tb_next
0163         return length
0164 
0165     def __repr__(self):
0166         return "<%s run=%i errors=%i failures=%i>" % \
0167                (_strclass(self.__class__), self.testsRun, len(self.errors),
0168                 len(self.failures))
0169 
0170 class TestCase:
0171     """A class whose instances are single test cases.
0172 
0173     By default, the test code itself should be placed in a method named
0174     'runTest'.
0175 
0176     If the fixture may be used for many test cases, create as
0177     many test methods as are needed. When instantiating such a TestCase
0178     subclass, specify in the constructor arguments the name of the test method
0179     that the instance is to execute.
0180 
0181     Test authors should subclass TestCase for their own tests. Construction
0182     and deconstruction of the test's environment ('fixture') can be
0183     implemented by overriding the 'setUp' and 'tearDown' methods respectively.
0184 
0185     If it is necessary to override the __init__ method, the base class
0186     __init__ method must always be called. It is important that subclasses
0187     should not change the signature of their __init__ method, since instances
0188     of the classes are instantiated automatically by parts of the framework
0189     in order to be run.
0190     """
0191 
0192     # This attribute determines which exception will be raised when
0193     # the instance's assertion methods fail; test methods raising this
0194     # exception will be deemed to have 'failed' rather than 'errored'
0195 
0196     failureException = AssertionError
0197 
0198     def __init__(self, methodName='runTest'):
0199         """Create an instance of the class that will use the named test
0200            method when executed. Raises a ValueError if the instance does
0201            not have a method with the specified name.
0202         """
0203         try:
0204             self.__testMethodName = methodName
0205             testMethod = getattr(self, methodName)
0206             self.__testMethodDoc = testMethod.__doc__
0207         except AttributeError:
0208             raise ValueError, "no such test method in %s: %s" % \
0209                   (self.__class__, methodName)
0210 
0211     def setUp(self):
0212         "Hook method for setting up the test fixture before exercising it."
0213         pass
0214 
0215     def tearDown(self):
0216         "Hook method for deconstructing the test fixture after testing it."
0217         pass
0218 
0219     def countTestCases(self):
0220         return 1
0221 
0222     def defaultTestResult(self):
0223         return TestResult()
0224 
0225     def shortDescription(self):
0226         """Returns a one-line description of the test, or None if no
0227         description has been provided.
0228 
0229         The default implementation of this method returns the first line of
0230         the specified test method's docstring.
0231         """
0232         doc = self.__testMethodDoc
0233         return doc and doc.split("\n")[0].strip() or None
0234 
0235     def id(self):
0236         return "%s.%s" % (_strclass(self.__class__), self.__testMethodName)
0237 
0238     def __str__(self):
0239         return "%s (%s)" % (self.__testMethodName, _strclass(self.__class__))
0240 
0241     def __repr__(self):
0242         return "<%s testMethod=%s>" % \
0243                (_strclass(self.__class__), self.__testMethodName)
0244 
0245     def run(self, result=None):
0246         if result is None: result = self.defaultTestResult()
0247         result.startTest(self)
0248         testMethod = getattr(self, self.__testMethodName)
0249         try:
0250             try:
0251                 self.setUp()
0252             except KeyboardInterrupt:
0253                 raise
0254             except:
0255                 result.addError(self, self.__exc_info())
0256                 return
0257 
0258             ok = False
0259             try:
0260                 testMethod()
0261                 ok = True
0262             except self.failureException:
0263                 result.addFailure(self, self.__exc_info())
0264             except KeyboardInterrupt:
0265                 raise
0266             except:
0267                 result.addError(self, self.__exc_info())
0268 
0269             try:
0270                 self.tearDown()
0271             except KeyboardInterrupt:
0272                 raise
0273             except:
0274                 result.addError(self, self.__exc_info())
0275                 ok = False
0276             if ok: result.addSuccess(self)
0277         finally:
0278             result.stopTest(self)
0279 
0280     __call__ = run
0281 
0282     def debug(self):
0283         """Run the test without collecting errors in a TestResult"""
0284         self.setUp()
0285         getattr(self, self.__testMethodName)()
0286         self.tearDown()
0287 
0288     def __exc_info(self):
0289         """Return a version of sys.exc_info() with the traceback frame
0290            minimised; usually the top level of the traceback frame is not
0291            needed.
0292         """
0293         exctype, excvalue, tb = sys.exc_info()
0294         if sys.platform[:4] == 'java': ## tracebacks look different in Jython
0295             return (exctype, excvalue, tb)
0296         return (exctype, excvalue, tb)
0297 
0298     def fail(self, msg=None):
0299         """Fail immediately, with the given message."""
0300         raise self.failureException, msg
0301 
0302     def failIf(self, expr, msg=None):
0303         "Fail the test if the expression is true."
0304         if expr: raise self.failureException, msg
0305 
0306     def failUnless(self, expr, msg=None):
0307         """Fail the test unless the expression is true."""
0308         if not expr: raise self.failureException, msg
0309 
0310     def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
0311         """Fail unless an exception of class excClass is thrown
0312            by callableObj when invoked with arguments args and keyword
0313            arguments kwargs. If a different type of exception is
0314            thrown, it will not be caught, and the test case will be
0315            deemed to have suffered an error, exactly as for an
0316            unexpected exception.
0317         """
0318         try:
0319             callableObj(*args, **kwargs)
0320         except excClass:
0321             return
0322         else:
0323             if hasattr(excClass,'__name__'): excName = excClass.__name__
0324             else: excName = str(excClass)
0325             raise self.failureException, "%s not raised" % excName
0326 
0327     def failUnlessEqual(self, first, second, msg=None):
0328         """Fail if the two objects are unequal as determined by the '=='
0329            operator.
0330         """
0331         if not first == second:
0332             raise self.failureException, \
0333                   (msg or '%r != %r' % (first, second))
0334 
0335     def failIfEqual(self, first, second, msg=None):
0336         """Fail if the two objects are equal as determined by the '=='
0337            operator.
0338         """
0339         if first == second:
0340             raise self.failureException, \
0341                   (msg or '%r == %r' % (first, second))
0342 
0343     def failUnlessAlmostEqual(self, first, second, places=7, msg=None):
0344         """Fail if the two objects are unequal as determined by their
0345            difference rounded to the given number of decimal places
0346            (default 7) and comparing to zero.
0347 
0348            Note that decimal places (from zero) are usually not the same
0349            as significant digits (measured from the most signficant digit).
0350         """
0351         if round(second-first, places) != 0:
0352             raise self.failureException, \
0353                   (msg or '%r != %r within %r places' % (first, second, places))
0354 
0355     def failIfAlmostEqual(self, first, second, places=7, msg=None):
0356         """Fail if the two objects are equal as determined by their
0357            difference rounded to the given number of decimal places
0358            (default 7) and comparing to zero.
0359 
0360            Note that decimal places (from zero) are usually not the same
0361            as significant digits (measured from the most signficant digit).
0362         """
0363         if round(second-first, places) == 0:
0364             raise self.failureException, \
0365                   (msg or '%r == %r within %r places' % (first, second, places))
0366 
0367     # Synonyms for assertion methods
0368 
0369     assertEqual = assertEquals = failUnlessEqual
0370 
0371     assertNotEqual = assertNotEquals = failIfEqual
0372 
0373     assertAlmostEqual = assertAlmostEquals = failUnlessAlmostEqual
0374 
0375     assertNotAlmostEqual = assertNotAlmostEquals = failIfAlmostEqual
0376 
0377     assertRaises = failUnlessRaises
0378 
0379     assert_ = assertTrue = failUnless
0380 
0381     assertFalse = failIf
0382 
0383 
0384 
0385 class TestSuite:
0386     """A test suite is a composite test consisting of a number of TestCases.
0387 
0388     For use, create an instance of TestSuite, then add test case instances.
0389     When all tests have been added, the suite can be passed to a test
0390     runner, such as TextTestRunner. It will run the individual test cases
0391     in the order in which they were added, aggregating the results. When
0392     subclassing, do not forget to call the base class constructor.
0393     """
0394     def __init__(self, tests=()):
0395         self._tests = []
0396         self.addTests(tests)
0397 
0398     def __repr__(self):
0399         return "<%s tests=%s>" % (_strclass(self.__class__), self._tests)
0400 
0401     __str__ = __repr__
0402 
0403     def __iter__(self):
0404         return iter(self._tests)
0405 
0406     def countTestCases(self):
0407         cases = 0
0408         for test in self._tests:
0409             cases += test.countTestCases()
0410         return cases
0411 
0412     def addTest(self, test):
0413         self._tests.append(test)
0414 
0415     def addTests(self, tests):
0416         for test in tests:
0417             self.addTest(test)
0418 
0419     def run(self, result):
0420         return self(result)
0421 
0422     def __call__(self, result):
0423         for test in self._tests:
0424             if result.shouldStop:
0425                 break
0426             test(result)
0427         return result
0428 
0429     def debug(self):
0430         """Run the tests without collecting errors in a TestResult"""
0431         for test in self._tests: test.debug()
0432 
0433 
0434 class FunctionTestCase(TestCase):
0435     """A test case that wraps a test function.
0436 
0437     This is useful for slipping pre-existing test functions into the
0438     PyUnit framework. Optionally, set-up and tidy-up functions can be
0439     supplied. As with TestCase, the tidy-up ('tearDown') function will
0440     always be called if the set-up ('setUp') function ran successfully.
0441     """
0442 
0443     def __init__(self, testFunc, setUp=None, tearDown=None,
0444                  description=None):
0445         TestCase.__init__(self)
0446         self.__setUpFunc = setUp
0447         self.__tearDownFunc = tearDown
0448         self.__testFunc = testFunc
0449         self.__description = description
0450 
0451     def setUp(self):
0452         if self.__setUpFunc is not None:
0453             self.__setUpFunc()
0454 
0455     def tearDown(self):
0456         if self.__tearDownFunc is not None:
0457             self.__tearDownFunc()
0458 
0459     def runTest(self):
0460         self.__testFunc()
0461 
0462     def id(self):
0463         return self.__testFunc.__name__
0464 
0465     def __str__(self):
0466         return "%s (%s)" % (_strclass(self.__class__), self.__testFunc.__name__)
0467 
0468     def __repr__(self):
0469         return "<%s testFunc=%s>" % (_strclass(self.__class__), self.__testFunc)
0470 
0471     def shortDescription(self):
0472         if self.__description is not None: return self.__description
0473         doc = self.__testFunc.__doc__
0474         return doc and doc.split("\n")[0].strip() or None
0475 
0476 
0477 
0478 ##############################################################################
0479 # Locating and loading tests
0480 ##############################################################################
0481 
0482 class TestLoader:
0483     """This class is responsible for loading tests according to various
0484     criteria and returning them wrapped in a Test
0485     """
0486     testMethodPrefix = 'test'
0487     sortTestMethodsUsing = cmp
0488     suiteClass = TestSuite
0489 
0490     def loadTestsFromTestCase(self, testCaseClass):
0491         """Return a suite of all tests cases contained in testCaseClass"""
0492         testCaseNames = self.getTestCaseNames(testCaseClass)
0493         if not testCaseNames and hasattr(testCaseClass, 'runTest'):
0494             testCaseNames = ['runTest']
0495         return self.suiteClass(map(testCaseClass, testCaseNames))
0496 
0497     def loadTestsFromModule(self, module):
0498         """Return a suite of all tests cases contained in the given module"""
0499         tests = []
0500         for name in dir(module):
0501             obj = getattr(module, name)
0502             if (isinstance(obj, (type, types.ClassType)) and
0503                 issubclass(obj, TestCase)):
0504                 tests.append(self.loadTestsFromTestCase(obj))
0505         return self.suiteClass(tests)
0506 
0507     def loadTestsFromName(self, name, module=None):
0508         """Return a suite of all tests cases given a string specifier.
0509 
0510         The name may resolve either to a module, a test case class, a
0511         test method within a test case class, or a callable object which
0512         returns a TestCase or TestSuite instance.
0513 
0514         The method optionally resolves the names relative to a given module.
0515         """
0516         parts = name.split('.')
0517         if module is None:
0518             parts_copy = parts[:]
0519             while parts_copy:
0520                 try:
0521                     module = __import__('.'.join(parts_copy))
0522                     break
0523                 except ImportError:
0524                     del parts_copy[-1]
0525                     if not parts_copy: raise
0526             parts = parts[1:]
0527         obj = module
0528         for part in parts:
0529             parent, obj = obj, getattr(obj, part)
0530 
0531         if type(obj) == types.ModuleType:
0532             return self.loadTestsFromModule(obj)
0533         elif (isinstance(obj, (type, types.ClassType)) and
0534               issubclass(obj, TestCase)):
0535             return self.loadTestsFromTestCase(obj)
0536         elif type(obj) == types.UnboundMethodType:
0537             return parent(obj.__name__)
0538         elif isinstance(obj, TestSuite):
0539             return obj
0540         elif callable(obj):
0541             test = obj()
0542             if not isinstance(test, (TestCase, TestSuite)):
0543                 raise ValueError, \
0544                       "calling %s returned %s, not a test" % (obj,test)
0545             return test
0546         else:
0547             raise ValueError, "don't know how to make test from: %s" % obj
0548 
0549     def loadTestsFromNames(self, names, module=None):
0550         """Return a suite of all tests cases found using the given sequence
0551         of string specifiers. See 'loadTestsFromName()'.
0552         """
0553         suites = [self.loadTestsFromName(name, module) for name in names]
0554         return self.suiteClass(suites)
0555 
0556     def getTestCaseNames(self, testCaseClass):
0557         """Return a sorted sequence of method names found within testCaseClass
0558         """
0559         def isTestMethod(attrname, testCaseClass=testCaseClass, prefix=self.testMethodPrefix):
0560             return attrname.startswith(prefix) and callable(getattr(testCaseClass, attrname))
0561         testFnNames = filter(isTestMethod, dir(testCaseClass))
0562         for baseclass in testCaseClass.__bases__:
0563             for testFnName in self.getTestCaseNames(baseclass):
0564                 if testFnName not in testFnNames:  # handle overridden methods
0565                     testFnNames.append(testFnName)
0566         if self.sortTestMethodsUsing:
0567             testFnNames.sort(self.sortTestMethodsUsing)
0568         return testFnNames
0569 
0570 
0571 
0572 defaultTestLoader = TestLoader()
0573 
0574 
0575 ##############################################################################
0576 # Patches for old functions: these functions should be considered obsolete
0577 ##############################################################################
0578 
0579 def _makeLoader(prefix, sortUsing, suiteClass=None):
0580     loader = TestLoader()
0581     loader.sortTestMethodsUsing = sortUsing
0582     loader.testMethodPrefix = prefix
0583     if suiteClass: loader.suiteClass = suiteClass
0584     return loader
0585 
0586 def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
0587     return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
0588 
0589 def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
0590     return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
0591 
0592 def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
0593     return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
0594 
0595 
0596 ##############################################################################
0597 # Text UI
0598 ##############################################################################
0599 
0600 class _WritelnDecorator:
0601     """Used to decorate file-like objects with a handy 'writeln' method"""
0602     def __init__(self,stream):
0603         self.stream = stream
0604 
0605     def __getattr__(self, attr):
0606         return getattr(self.stream,attr)
0607 
0608     def writeln(self, arg=None):
0609         if arg: self.write(arg)
0610         self.write('\n') # text-mode streams translate to \r\n if needed
0611 
0612 
0613 class _TextTestResult(TestResult):
0614     """A test result class that can print formatted text results to a stream.
0615 
0616     Used by TextTestRunner.
0617     """
0618     separator1 = '=' * 70
0619     separator2 = '-' * 70
0620 
0621     def __init__(self, stream, descriptions, verbosity):
0622         TestResult.__init__(self)
0623         self.stream = stream
0624         self.showAll = verbosity > 1
0625         self.dots = verbosity == 1
0626         self.descriptions = descriptions
0627 
0628     def getDescription(self, test):
0629         if self.descriptions:
0630             return test.shortDescription() or str(test)
0631         else:
0632             return str(test)
0633 
0634     def startTest(self, test):
0635         TestResult.startTest(self, test)
0636         if self.showAll:
0637             self.stream.write(self.getDescription(test))
0638             self.stream.write(" ... ")
0639 
0640     def addSuccess(self, test):
0641         TestResult.addSuccess(self, test)
0642         if self.showAll:
0643             self.stream.writeln("ok")
0644         elif self.dots:
0645             self.stream.write('.')
0646 
0647     def addError(self, test, err):
0648         TestResult.addError(self, test, err)
0649         if self.showAll:
0650             self.stream.writeln("ERROR")
0651         elif self.dots:
0652             self.stream.write('E')
0653 
0654     def addFailure(self, test, err):
0655         TestResult.addFailure(self, test, err)
0656         if self.showAll:
0657             self.stream.writeln("FAIL")
0658         elif self.dots:
0659             self.stream.write('F')
0660 
0661     def printErrors(self):
0662         if self.dots or self.showAll:
0663             self.stream.writeln()
0664         self.printErrorList('ERROR', self.errors)
0665         self.printErrorList('FAIL', self.failures)
0666 
0667     def printErrorList(self, flavour, errors):
0668         for test, err in errors:
0669             self.stream.writeln(self.separator1)
0670             self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
0671             self.stream.writeln(self.separator2)
0672             self.stream.writeln("%s" % err)
0673 
0674 
0675 class TextTestRunner:
0676     """A test runner class that displays results in textual form.
0677 
0678     It prints out the names of tests as they are run, errors as they
0679     occur, and a summary of the results at the end of the test run.
0680     """
0681     def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1):
0682         self.stream = _WritelnDecorator(stream)
0683         self.descriptions = descriptions
0684         self.verbosity = verbosity
0685 
0686     def _makeResult(self):
0687         return _TextTestResult(self.stream, self.descriptions, self.verbosity)
0688 
0689     def run(self, test):
0690         "Run the given test case or test suite."
0691         result = self._makeResult()
0692         startTime = time.time()
0693         test(result)
0694         stopTime = time.time()
0695         timeTaken = stopTime - startTime
0696         result.printErrors()
0697         self.stream.writeln(result.separator2)
0698         run = result.testsRun
0699         self.stream.writeln("Ran %d test%s in %.3fs" %
0700                             (run, run != 1 and "s" or "", timeTaken))
0701         self.stream.writeln()
0702         if not result.wasSuccessful():
0703             self.stream.write("FAILED (")
0704             failed, errored = map(len, (result.failures, result.errors))
0705             if failed:
0706                 self.stream.write("failures=%d" % failed)
0707             if errored:
0708                 if failed: self.stream.write(", ")
0709                 self.stream.write("errors=%d" % errored)
0710             self.stream.writeln(")")
0711         else:
0712             self.stream.writeln("OK")
0713         return result
0714 
0715 
0716 
0717 ##############################################################################
0718 # Facilities for running tests from the command line
0719 ##############################################################################
0720 
0721 class TestProgram:
0722     """A command-line program that runs a set of tests; this is primarily
0723        for making test modules conveniently executable.
0724     """
0725     USAGE = """\
0726 Usage: %(progName)s [options] [test] [...]
0727 
0728 Options:
0729   -h, --help       Show this message
0730   -v, --verbose    Verbose output
0731   -q, --quiet      Minimal output
0732 
0733 Examples:
0734   %(progName)s                               - run default set of tests
0735   %(progName)s MyTestSuite                   - run suite 'MyTestSuite'
0736   %(progName)s MyTestCase.testSomething      - run MyTestCase.testSomething
0737   %(progName)s MyTestCase                    - run all 'test*' test methods
0738                                                in MyTestCase
0739 """
0740     def __init__(self, module='__main__', defaultTest=None,
0741                  argv=None, testRunner=None, testLoader=defaultTestLoader):
0742         if type(module) == type(''):
0743             self.module = __import__(module)
0744             for part in module.split('.')[1:]:
0745                 self.module = getattr(self.module, part)
0746         else:
0747             self.module = module
0748         if argv is None:
0749             argv = sys.argv
0750         self.verbosity = 1
0751         self.defaultTest = defaultTest
0752         self.testRunner = testRunner
0753         self.testLoader = testLoader
0754         self.progName = os.path.basename(argv[0])
0755         self.parseArgs(argv)
0756         self.runTests()
0757 
0758     def usageExit(self, msg=None):
0759         if msg: print msg
0760         print self.USAGE % self.__dict__
0761         sys.exit(2)
0762 
0763     def parseArgs(self, argv):
0764         import getopt
0765         try:
0766             options, args = getopt.getopt(argv[1:], 'hHvq',
0767                                           ['help','verbose','quiet'])
0768             for opt, value in options:
0769                 if opt in ('-h','-H','--help'):
0770                     self.usageExit()
0771                 if opt in ('-q','--quiet'):
0772                     self.verbosity = 0
0773                 if opt in ('-v','--verbose'):
0774                     self.verbosity = 2
0775             if len(args) == 0 and self.defaultTest is None:
0776                 self.test = self.testLoader.loadTestsFromModule(self.module)
0777                 return
0778             if len(args) > 0:
0779                 self.testNames = args
0780             else:
0781                 self.testNames = (self.defaultTest,)
0782             self.createTests()
0783         except getopt.error, msg:
0784             self.usageExit(msg)
0785 
0786     def createTests(self):
0787         self.test = self.testLoader.loadTestsFromNames(self.testNames,
0788                                                        self.module)
0789 
0790     def runTests(self):
0791         if self.testRunner is None:
0792             self.testRunner = TextTestRunner(verbosity=self.verbosity)
0793         result = self.testRunner.run(self.test)
0794         sys.exit(not result.wasSuccessful())
0795 
0796 main = TestProgram
0797 
0798 
0799 ##############################################################################
0800 # Executing this module from the command line
0801 ##############################################################################
0802 
0803 if __name__ == "__main__":
0804     main(module=None)
0805 

Generated by PyXR 0.9.4
SourceForge.net Logo