unittest

Module unittest |
[hide private]
[frames] | no frames]

# Source Code for Module unittest

      1  #! /usr/bin/python2.5
      2  '''
      3  Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
      4  Smalltalk testing framework.
      5
      6  This module contains the core framework classes that form the basis of
      7  specific test cases and suites (TestCase, TestSuite etc.), and also a
      8  text-based utility class for running the tests and reporting the results
      9   (TextTestRunner).
     10
     11  Simple usage:
     12
     13      import unittest
     14
     15      class IntegerArithmenticTestCase(unittest.TestCase):
     16          def testAdd(self):  ## test method names begin 'test*'
     17              self.assertEquals((1 + 2), 3)
     18              self.assertEquals(0 + 1, 1)
     19          def testMultiply(self):
     20              self.assertEquals((0 * 10), 0)
     21              self.assertEquals((5 * 8), 40)
     22
     23      if __name__ == '__main__':
     24          unittest.main()
     25
     26  Further information is available in the bundled documentation, and from
     27
     28    http://pyunit.sourceforge.net/
     29
     30  Copyright (c) 1999-2003 Steve Purcell
     31  This module is free software, and you may redistribute it and/or modify
     32  it under the same terms as Python itself, so long as this copyright message
     33  and disclaimer are retained in their original form.
     34
     35  IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
     36  SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
     37  THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     38  DAMAGE.
     39
     40  THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
     41  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     42  PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
     43  AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
     44  SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     45  '''
     46
     47  __author__ = "Steve Purcell"
     48  __email__ = "stephen_purcell at yahoo dot com"
     49  __version__ = "#Revision: 1.63 $"[11:-2]
     50
     51  import time
     52  import sys
     53  import traceback
     54  import os
     55  import types
     56
     57  ##############################################################################
     58  # Exported classes and functions
     59  ##############################################################################
     60  __all__ = ['TestResult', 'TestCase', 'TestSuite', 'TextTestRunner',
     61             'TestLoader', 'FunctionTestCase', 'main', 'defaultTestLoader']
     62
     63  # Expose obsolete functions for backwards compatibility
     64  __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
     65
     66
     67  ##############################################################################
     68  # Backward compatibility
     69  ##############################################################################
     70  if sys.version_info[:2] < (2, 2):
     71      False, True = 0, 1
     72 -    def isinstance(obj, clsinfo):
     73          import __builtin__
     74          if type(clsinfo) in (tuple, list):
     75              for cls in clsinfo:
     76                  if cls is type: cls = types.ClassType
     77                  if __builtin__.isinstance(obj, cls):
     78                      return 1
     79              return 0
     80          else: return __builtin__.isinstance(obj, clsinfo)
     81
     82
     83  ##############################################################################
     84  # Test framework core
     85  ##############################################################################
     86
     87  # All classes defined herein are 'new-style' classes, allowing use of 'super()'
     88  __metaclass__ = type
     89
     90 -def _strclass(cls):
     91      return "%s.%s" % (cls.__module__, cls.__name__)
     92
     93  __unittest = 1
     94
     95 -class TestResult:
     96      """Holder for test result information.
     97
     98      Test results are automatically managed by the TestCase and TestSuite
     99      classes, and do not need to be explicitly manipulated by writers of tests.
    100
    101      Each instance holds the total number of tests run, and collections of
    102      failures and errors that occurred among those test runs. The collections
    103      contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
    104      formatted traceback of the error that occurred.
    105      """
    106 -    def __init__(self):
    107          self.failures = []
    108          self.errors = []
    109          self.testsRun = 0
    110          self.shouldStop = 0
    111
    112 -    def startTest(self, test):
    113          "Called when the given test is about to be run"
    114          self.testsRun = self.testsRun + 1
    115
    116 -    def stopTest(self, test):
    117          "Called when the given test has been run"
    118          pass
    119
    120 -    def addError(self, test, err):
    121          """Called when an error has occurred. 'err' is a tuple of values as
    122          returned by sys.exc_info().
    123          """
    124          self.errors.append((test, self._exc_info_to_string(err, test)))
    125
    126 -    def addFailure(self, test, err):
    127          """Called when an error has occurred. 'err' is a tuple of values as
    128          returned by sys.exc_info()."""
    129          self.failures.append((test, self._exc_info_to_string(err, test)))
    130
    131 -    def addSuccess(self, test):
    132          "Called when a test has completed successfully"
    133          pass
    134
    135 -    def wasSuccessful(self):
    136          "Tells whether or not this result was a success"
    137          return len(self.failures) == len(self.errors) == 0
    138
    139 -    def stop(self):
    140          "Indicates that the tests should be aborted"
    141          self.shouldStop = True
    142
    143 -    def _exc_info_to_string(self, err, test):
    144          """Converts a sys.exc_info()-style tuple of values into a string."""
    145          exctype, value, tb = err
    146          # Skip test runner traceback levels
    147          while tb and self._is_relevant_tb_level(tb):
    148              tb = tb.tb_next
    149          if exctype is test.failureException:
    150              # Skip assert*() traceback levels
    151              length = self._count_relevant_tb_levels(tb)
    152              return ''.join(traceback.format_exception(exctype, value, tb, length))
    153          return ''.join(traceback.format_exception(exctype, value, tb))
    154
    155 -    def _is_relevant_tb_level(self, tb):
    156          return tb.tb_frame.f_globals.has_key('__unittest')
    157
    158 -    def _count_relevant_tb_levels(self, tb):
    159          length = 0
    160          while tb and not self._is_relevant_tb_level(tb):
    161              length += 1
    162              tb = tb.tb_next
    163          return length
    164
    165 -    def __repr__(self):
    166          return "<%s run=%i errors=%i failures=%i>" % \
    167                 (_strclass(self.__class__), self.testsRun, len(self.errors),
    168                  len(self.failures))
    169
    170 -class TestCase:
    171      """A class whose instances are single test cases.
    172
    173      By default, the test code itself should be placed in a method named
    174      'runTest'.
    175
    176      If the fixture may be used for many test cases, create as
    177      many test methods as are needed. When instantiating such a TestCase
    178      subclass, specify in the constructor arguments the name of the test method
    179      that the instance is to execute.
    180
    181      Test authors should subclass TestCase for their own tests. Construction
    182      and deconstruction of the test's environment ('fixture') can be
    183      implemented by overriding the 'setUp' and 'tearDown' methods respectively.
    184
    185      If it is necessary to override the __init__ method, the base class
    186      __init__ method must always be called. It is important that subclasses
    187      should not change the signature of their __init__ method, since instances
    188      of the classes are instantiated automatically by parts of the framework
    189      in order to be run.
    190      """
    191
    192      # This attribute determines which exception will be raised when
    193      # the instance's assertion methods fail; test methods raising this
    194      # exception will be deemed to have 'failed' rather than 'errored'
    195
    196      failureException = AssertionError
    197
    198 -    def __init__(self, methodName='runTest'):
    199          """Create an instance of the class that will use the named test
    200             method when executed. Raises a ValueError if the instance does
    201             not have a method with the specified name.
    202          """
    203          try:
    204              self._testMethodName = methodName
    205              testMethod = getattr(self, methodName)
    206              self._testMethodDoc = testMethod.__doc__
    207          except AttributeError:
    208              raise ValueError, "no such test method in %s: %s" % \
    209                    (self.__class__, methodName)
    210
    211 -    def setUp(self):
    212          "Hook method for setting up the test fixture before exercising it."
    213          pass
    214
    215 -    def tearDown(self):
    216          "Hook method for deconstructing the test fixture after testing it."
    217          pass
    218
    219 -    def countTestCases(self):
    220          return 1
    221
    222 -    def defaultTestResult(self):
    223          return TestResult()
    224
    225 -    def shortDescription(self):
    226          """Returns a one-line description of the test, or None if no
    227          description has been provided.
    228
    229          The default implementation of this method returns the first line of
    230          the specified test method's docstring.
    231          """
    232          doc = self._testMethodDoc
    233          return doc and doc.split("\n")[0].strip() or None
    234
    235 -    def id(self):
    236          return "%s.%s" % (_strclass(self.__class__), self._testMethodName)
    237
    238 -    def __str__(self):
    239          return "%s (%s)" % (self._testMethodName, _strclass(self.__class__))
    240
    241 -    def __repr__(self):
    242          return "<%s testMethod=%s>" % \
    243                 (_strclass(self.__class__), self._testMethodName)
    244
    245 -    def run(self, result=None):
    246          if result is None: result = self.defaultTestResult()
    247          result.startTest(self)
    248          testMethod = getattr(self, self._testMethodName)
    249          try:
    250              try:
    251                  self.setUp()
    252              except KeyboardInterrupt:
    253                  raise
    254              except:
    255                  result.addError(self, self._exc_info())
    256                  return
    257
    258              ok = False
    259              try:
    260                  testMethod()
    261                  ok = True
    262              except self.failureException:
    263                  result.addFailure(self, self._exc_info())
    264              except KeyboardInterrupt:
    265                  raise
    266              except:
    267                  result.addError(self, self._exc_info())
    268
    269              try:
    270                  self.tearDown()
    271              except KeyboardInterrupt:
    272                  raise
    273              except:
    274                  result.addError(self, self._exc_info())
    275                  ok = False
    276              if ok: result.addSuccess(self)
    277          finally:
    278              result.stopTest(self)
    279
    280 -    def __call__(self, *args, **kwds):
    281          return self.run(*args, **kwds)
    282
    283 -    def debug(self):
    284          """Run the test without collecting errors in a TestResult"""
    285          self.setUp()
    286          getattr(self, self._testMethodName)()
    287          self.tearDown()
    288
    289 -    def _exc_info(self):
    290          """Return a version of sys.exc_info() with the traceback frame
    291             minimised; usually the top level of the traceback frame is not
    292             needed.
    293          """
    294          exctype, excvalue, tb = sys.exc_info()
    295          if sys.platform[:4] == 'java': ## tracebacks look different in Jython
    296              return (exctype, excvalue, tb)
    297          return (exctype, excvalue, tb)
    298
    299 -    def fail(self, msg=None):
    300          """Fail immediately, with the given message."""
    301          raise self.failureException, msg
    302
    303 -    def failIf(self, expr, msg=None):
    304          "Fail the test if the expression is true."
    305          if expr: raise self.failureException, msg
    306
    307 -    def failUnless(self, expr, msg=None):
    308          """Fail the test unless the expression is true."""
    309          if not expr: raise self.failureException, msg
    310
    311 -    def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
    312          """Fail unless an exception of class excClass is thrown
    313             by callableObj when invoked with arguments args and keyword
    314             arguments kwargs. If a different type of exception is
    315             thrown, it will not be caught, and the test case will be
    316             deemed to have suffered an error, exactly as for an
    317             unexpected exception.
    318          """
    319          try:
    320              callableObj(*args, **kwargs)
    321          except excClass:
    322              return
    323          else:
    324              if hasattr(excClass,'__name__'): excName = excClass.__name__
    325              else: excName = str(excClass)
    326              raise self.failureException, "%s not raised" % excName
    327
    328 -    def failUnlessEqual(self, first, second, msg=None):
    329          """Fail if the two objects are unequal as determined by the '=='
    330             operator.
    331          """
    332          if not first == second:
    333              raise self.failureException, \
    334                    (msg or '%r != %r' % (first, second))
    335
    336 -    def failIfEqual(self, first, second, msg=None):
    337          """Fail if the two objects are equal as determined by the '=='
    338             operator.
    339          """
    340          if first == second:
    341              raise self.failureException, \
    342                    (msg or '%r == %r' % (first, second))
    343
    344 -    def failUnlessAlmostEqual(self, first, second, places=7, msg=None):
    345          """Fail if the two objects are unequal as determined by their
    346             difference rounded to the given number of decimal places
    347             (default 7) and comparing to zero.
    348
    349             Note that decimal places (from zero) are usually not the same
    350             as significant digits (measured from the most signficant digit).
    351          """
    352          if round(second-first, places) != 0:
    353              raise self.failureException, \
    354                    (msg or '%r != %r within %r places' % (first, second, places))
    355
    356 -    def failIfAlmostEqual(self, first, second, places=7, msg=None):
    357          """Fail if the two objects are equal as determined by their
    358             difference rounded to the given number of decimal places
    359             (default 7) and comparing to zero.
    360
    361             Note that decimal places (from zero) are usually not the same
    362             as significant digits (measured from the most signficant digit).
    363          """
    364          if round(second-first, places) == 0:
    365              raise self.failureException, \
    366                    (msg or '%r == %r within %r places' % (first, second, places))
    367
    368      # Synonyms for assertion methods
    369
    370      assertEqual = assertEquals = failUnlessEqual
    371
    372      assertNotEqual = assertNotEquals = failIfEqual
    373
    374      assertAlmostEqual = assertAlmostEquals = failUnlessAlmostEqual
    375
    376      assertNotAlmostEqual = assertNotAlmostEquals = failIfAlmostEqual
    377
    378      assertRaises = failUnlessRaises
    379
    380      assert_ = assertTrue = failUnless
    381
    382      assertFalse = failIf
    383
    384
    385
    386 -class TestSuite:
    387      """A test suite is a composite test consisting of a number of TestCases.
    388
    389      For use, create an instance of TestSuite, then add test case instances.
    390      When all tests have been added, the suite can be passed to a test
    391      runner, such as TextTestRunner. It will run the individual test cases
    392      in the order in which they were added, aggregating the results. When
    393      subclassing, do not forget to call the base class constructor.
    394      """
    395 -    def __init__(self, tests=()):
    396          self._tests = []
    397          self.addTests(tests)
    398
    399 -    def __repr__(self):
    400          return "<%s tests=%s>" % (_strclass(self.__class__), self._tests)
    401
    402      __str__ = __repr__
    403
    404 -    def __iter__(self):
    405          return iter(self._tests)
    406
    407 -    def countTestCases(self):
    408          cases = 0
    409          for test in self._tests:
    410              cases += test.countTestCases()
    411          return cases
    412
    413 -    def addTest(self, test):
    414          # sanity checks
    415          if not callable(test):
    416              raise TypeError("the test to add must be callable")
    417          if (isinstance(test, (type, types.ClassType)) and
    418              issubclass(test, (TestCase, TestSuite))):
    419              raise TypeError("TestCases and TestSuites must be instantiated "
    420                              "before passing them to addTest()")
    421          self._tests.append(test)
    422
    423 -    def addTests(self, tests):
    424          if isinstance(tests, basestring):
    425              raise TypeError("tests must be an iterable of tests, not a string")
    426          for test in tests:
    427              self.addTest(test)
    428
    429 -    def run(self, result):
    430          for test in self._tests:
    431              if result.shouldStop:
    432                  break
    433              test(result)
    434          return result
    435
    436 -    def __call__(self, *args, **kwds):
    437          return self.run(*args, **kwds)
    438
    439 -    def debug(self):
    440          """Run the tests without collecting errors in a TestResult"""
    441          for test in self._tests: test.debug()
    442
    443
    444 -class FunctionTestCase(TestCase):
    445      """A test case that wraps a test function.
    446
    447      This is useful for slipping pre-existing test functions into the
    448      PyUnit framework. Optionally, set-up and tidy-up functions can be
    449      supplied. As with TestCase, the tidy-up ('tearDown') function will
    450      always be called if the set-up ('setUp') function ran successfully.
    451      """
    452
    453 -    def __init__(self, testFunc, setUp=None, tearDown=None,
    454                   description=None):
    455          TestCase.__init__(self)
    456          self.__setUpFunc = setUp
    457          self.__tearDownFunc = tearDown
    458          self.__testFunc = testFunc
    459          self.__description = description
    460
    461 -    def setUp(self):
    462          if self.__setUpFunc is not None:
    463              self.__setUpFunc()
    464
    465 -    def tearDown(self):
    466          if self.__tearDownFunc is not None:
    467              self.__tearDownFunc()
    468
    469 -    def runTest(self):
    470          self.__testFunc()
    471
    472 -    def id(self):
    473          return self.__testFunc.__name__
    474
    475 -    def __str__(self):
    476          return "%s (%s)" % (_strclass(self.__class__), self.__testFunc.__name__)
    477
    478 -    def __repr__(self):
    479          return "<%s testFunc=%s>" % (_strclass(self.__class__), self.__testFunc)
    480
    481 -    def shortDescription(self):
    482          if self.__description is not None: return self.__description
    483          doc = self.__testFunc.__doc__
    484          return doc and doc.split("\n")[0].strip() or None
    485
    486
    487
    488  ##############################################################################
    489  # Locating and loading tests
    490  ##############################################################################
    491
    492 -class TestLoader:
    493      """This class is responsible for loading tests according to various
    494      criteria and returning them wrapped in a Test
    495      """
    496      testMethodPrefix = 'test'
    497      sortTestMethodsUsing = cmp
    498      suiteClass = TestSuite
    499
    500 -    def loadTestsFromTestCase(self, testCaseClass):
    501          """Return a suite of all tests cases contained in testCaseClass"""
    502          if issubclass(testCaseClass, TestSuite):
    503              raise TypeError("Test cases should not be derived from TestSuite. Maybe you meant to derive from TestCase?")
    504          testCaseNames = self.getTestCaseNames(testCaseClass)
    505          if not testCaseNames and hasattr(testCaseClass, 'runTest'):
    506              testCaseNames = ['runTest']
    507          return self.suiteClass(map(testCaseClass, testCaseNames))
    508
    509 -    def loadTestsFromModule(self, module):
    510          """Return a suite of all tests cases contained in the given module"""
    511          tests = []
    512          for name in dir(module):
    513              obj = getattr(module, name)
    514              if (isinstance(obj, (type, types.ClassType)) and
    515                  issubclass(obj, TestCase)):
    516                  tests.append(self.loadTestsFromTestCase(obj))
    517          return self.suiteClass(tests)
    518
    519 -    def loadTestsFromName(self, name, module=None):
    520          """Return a suite of all tests cases given a string specifier.
    521
    522          The name may resolve either to a module, a test case class, a
    523          test method within a test case class, or a callable object which
    524          returns a TestCase or TestSuite instance.
    525
    526          The method optionally resolves the names relative to a given module.
    527          """
    528          parts = name.split('.')
    529          if module is None:
    530              parts_copy = parts[:]
    531              while parts_copy:
    532                  try:
    533                      module = __import__('.'.join(parts_copy))
    534                      break
    535                  except ImportError:
    536                      del parts_copy[-1]
    537                      if not parts_copy: raise
    538              parts = parts[1:]
    539          obj = module
    540          for part in parts:
    541              parent, obj = obj, getattr(obj, part)
    542
    543          if type(obj) == types.ModuleType:
    544              return self.loadTestsFromModule(obj)
    545          elif (isinstance(obj, (type, types.ClassType)) and
    546                issubclass(obj, TestCase)):
    547              return self.loadTestsFromTestCase(obj)
    548          elif type(obj) == types.UnboundMethodType:
    549              return parent(obj.__name__)
    550          elif isinstance(obj, TestSuite):
    551              return obj
    552          elif callable(obj):
    553              test = obj()
    554              if not isinstance(test, (TestCase, TestSuite)):
    555                  raise ValueError, \
    556                        "calling %s returned %s, not a test" % (obj,test)
    557              return test
    558          else:
    559              raise ValueError, "don't know how to make test from: %s" % obj
    560
    561 -    def loadTestsFromNames(self, names, module=None):
    562          """Return a suite of all tests cases found using the given sequence
    563          of string specifiers. See 'loadTestsFromName()'.
    564          """
    565          suites = [self.loadTestsFromName(name, module) for name in names]
    566          return self.suiteClass(suites)
    567
    568 -    def getTestCaseNames(self, testCaseClass):
    569          """Return a sorted sequence of method names found within testCaseClass
    570          """
    571          def isTestMethod(attrname, testCaseClass=testCaseClass, prefix=self.testMethodPrefix):
    572              return attrname.startswith(prefix) and callable(getattr(testCaseClass, attrname))
    573          testFnNames = filter(isTestMethod, dir(testCaseClass))
    574          for baseclass in testCaseClass.__bases__:
    575              for testFnName in self.getTestCaseNames(baseclass):
    576                  if testFnName not in testFnNames:  # handle overridden methods
    577                      testFnNames.append(testFnName)
    578          if self.sortTestMethodsUsing:
    579              testFnNames.sort(self.sortTestMethodsUsing)
    580          return testFnNames
    581
    582
    583
    584  defaultTestLoader = TestLoader()
    585
    586
    587  ##############################################################################
    588  # Patches for old functions: these functions should be considered obsolete
    589  ##############################################################################
    590
    591 -def _makeLoader(prefix, sortUsing, suiteClass=None):
    592      loader = TestLoader()
    593      loader.sortTestMethodsUsing = sortUsing
    594      loader.testMethodPrefix = prefix
    595      if suiteClass: loader.suiteClass = suiteClass
    596      return loader
    597
    598 -def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
    599      return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
    600
    601 -def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
    602      return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
    603
    604 -def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
    605      return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
    606
    607
    608  ##############################################################################
    609  # Text UI
    610  ##############################################################################
    611
    612 -class _WritelnDecorator:
    613      """Used to decorate file-like objects with a handy 'writeln' method"""
    614 -    def __init__(self,stream):
    615          self.stream = stream
    616
    617 -    def __getattr__(self, attr):
    618          return getattr(self.stream,attr)
    619
    620 -    def writeln(self, arg=None):
    621          if arg: self.write(arg)
    622          self.write('\n') # text-mode streams translate to \r\n if needed
    623
    624
    625 -class _TextTestResult(TestResult):
    626      """A test result class that can print formatted text results to a stream.
    627
    628      Used by TextTestRunner.
    629      """
    630      separator1 = '=' * 70
    631      separator2 = '-' * 70
    632
    633 -    def __init__(self, stream, descriptions, verbosity):
    634          TestResult.__init__(self)
    635          self.stream = stream
    636          self.showAll = verbosity > 1
    637          self.dots = verbosity == 1
    638          self.descriptions = descriptions
    639
    640 -    def getDescription(self, test):
    641          if self.descriptions:
    642              return test.shortDescription() or str(test)
    643          else:
    644              return str(test)
    645
    646 -    def startTest(self, test):
    647          TestResult.startTest(self, test)
    648          if self.showAll:
    649              self.stream.write(self.getDescription(test))
    650              self.stream.write(" ... ")
    651
    652 -    def addSuccess(self, test):
    653          TestResult.addSuccess(self, test)
    654          if self.showAll:
    655              self.stream.writeln("ok")
    656          elif self.dots:
    657              self.stream.write('.')
    658
    659 -    def addError(self, test, err):
    660          TestResult.addError(self, test, err)
    661          if self.showAll:
    662              self.stream.writeln("ERROR")
    663          elif self.dots:
    664              self.stream.write('E')
    665
    666 -    def addFailure(self, test, err):
    667          TestResult.addFailure(self, test, err)
    668          if self.showAll:
    669              self.stream.writeln("FAIL")
    670          elif self.dots:
    671              self.stream.write('F')
    672
    673 -    def printErrors(self):
    674          if self.dots or self.showAll:
    675              self.stream.writeln()
    676          self.printErrorList('ERROR', self.errors)
    677          self.printErrorList('FAIL', self.failures)
    678
    679 -    def printErrorList(self, flavour, errors):
    680          for test, err in errors:
    681              self.stream.writeln(self.separator1)
    682              self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
    683              self.stream.writeln(self.separator2)
    684              self.stream.writeln("%s" % err)
    685
    686
    687 -class TextTestRunner:
    688      """A test runner class that displays results in textual form.
    689
    690      It prints out the names of tests as they are run, errors as they
    691      occur, and a summary of the results at the end of the test run.
    692      """
    693 -    def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1):
    694          self.stream = _WritelnDecorator(stream)
    695          self.descriptions = descriptions
    696          self.verbosity = verbosity
    697
    698 -    def _makeResult(self):
    699          return _TextTestResult(self.stream, self.descriptions, self.verbosity)
    700
    701 -    def run(self, test):
    702          "Run the given test case or test suite."
    703          result = self._makeResult()
    704          startTime = time.time()
    705          test(result)
    706          stopTime = time.time()
    707          timeTaken = stopTime - startTime
    708          result.printErrors()
    709          self.stream.writeln(result.separator2)
    710          run = result.testsRun
    711          self.stream.writeln("Ran %d test%s in %.3fs" %
    712                              (run, run != 1 and "s" or "", timeTaken))
    713          self.stream.writeln()
    714          if not result.wasSuccessful():
    715              self.stream.write("FAILED (")
    716              failed, errored = map(len, (result.failures, result.errors))
    717              if failed:
    718                  self.stream.write("failures=%d" % failed)
    719              if errored:
    720                  if failed: self.stream.write(", ")
    721                  self.stream.write("errors=%d" % errored)
    722              self.stream.writeln(")")
    723          else:
    724              self.stream.writeln("OK")
    725          return result
    726
    727
    728
    729  ##############################################################################
    730  # Facilities for running tests from the command line
    731  ##############################################################################
    732
    733 -class TestProgram:
    734      """A command-line program that runs a set of tests; this is primarily
    735         for making test modules conveniently executable.
    736      """
    737      USAGE = """\
    738  Usage: %(progName)s [options] [test] [...]
    739
    740  Options:
    741    -h, --help       Show this message
    742    -v, --verbose    Verbose output
    743    -q, --quiet      Minimal output
    744
    745  Examples:
    746    %(progName)s                               - run default set of tests
    747    %(progName)s MyTestSuite                   - run suite 'MyTestSuite'
    748    %(progName)s MyTestCase.testSomething      - run MyTestCase.testSomething
    749    %(progName)s MyTestCase                    - run all 'test*' test methods
    750                                                 in MyTestCase
    751  """
    752 -    def __init__(self, module='__main__', defaultTest=None,
    753                   argv=None, testRunner=None, testLoader=defaultTestLoader):
    754          if type(module) == type(''):
    755              self.module = __import__(module)
    756              for part in module.split('.')[1:]:
    757                  self.module = getattr(self.module, part)
    758          else:
    759              self.module = module
    760          if argv is None:
    761              argv = sys.argv
    762          self.verbosity = 1
    763          self.defaultTest = defaultTest
    764          self.testRunner = testRunner
    765          self.testLoader = testLoader
    766          self.progName = os.path.basename(argv[0])
    767          self.parseArgs(argv)
    768          self.runTests()
    769
    770 -    def usageExit(self, msg=None):
    771          if msg: print msg
    772          print self.USAGE % self.__dict__
    773          sys.exit(2)
    774
    775 -    def parseArgs(self, argv):
    776          import getopt
    777          try:
    778              options, args = getopt.getopt(argv[1:], 'hHvq',
    779                                            ['help','verbose','quiet'])
    780              for opt, value in options:
    781                  if opt in ('-h','-H','--help'):
    782                      self.usageExit()
    783                  if opt in ('-q','--quiet'):
    784                      self.verbosity = 0
    785                  if opt in ('-v','--verbose'):
    786                      self.verbosity = 2
    787              if len(args) == 0 and self.defaultTest is None:
    788                  self.test = self.testLoader.loadTestsFromModule(self.module)
    789                  return
    790              if len(args) > 0:
    791                  self.testNames = args
    792              else:
    793                  self.testNames = (self.defaultTest,)
    794              self.createTests()
    795          except getopt.error, msg:
    796              self.usageExit(msg)
    797
    798 -    def createTests(self):
    799          self.test = self.testLoader.loadTestsFromNames(self.testNames,
    800                                                         self.module)
    801
    802 -    def runTests(self):
    803          if self.testRunner is None:
    804              self.testRunner = TextTestRunner(verbosity=self.verbosity)
    805          result = self.testRunner.run(self.test)
    806          sys.exit(not result.wasSuccessful())
    807
    808  main = TestProgram
    809
    810
    811  ##############################################################################
    812  # Executing this module from the command line
    813  ##############################################################################
    814
    815  if __name__ == "__main__":
    816      main(module=None)
    817