Home | History | Annotate | Download | only in unittest
      1 """Running tests"""
      2 
      3 import sys
      4 import time
      5 
      6 from . import result
      7 from .signals import registerResult
      8 
      9 __unittest = True
     10 
     11 
     12 class _WritelnDecorator(object):
     13     """Used to decorate file-like objects with a handy 'writeln' method"""
     14     def __init__(self,stream):
     15         self.stream = stream
     16 
     17     def __getattr__(self, attr):
     18         if attr in ('stream', '__getstate__'):
     19             raise AttributeError(attr)
     20         return getattr(self.stream,attr)
     21 
     22     def writeln(self, arg=None):
     23         if arg:
     24             self.write(arg)
     25         self.write('\n') # text-mode streams translate to \r\n if needed
     26 
     27 
     28 class TextTestResult(result.TestResult):
     29     """A test result class that can print formatted text results to a stream.
     30 
     31     Used by TextTestRunner.
     32     """
     33     separator1 = '=' * 70
     34     separator2 = '-' * 70
     35 
     36     def __init__(self, stream, descriptions, verbosity):
     37         super(TextTestResult, self).__init__(stream, descriptions, verbosity)
     38         self.stream = stream
     39         self.showAll = verbosity > 1
     40         self.dots = verbosity == 1
     41         self.descriptions = descriptions
     42 
     43     def getDescription(self, test):
     44         doc_first_line = test.shortDescription()
     45         if self.descriptions and doc_first_line:
     46             return '\n'.join((str(test), doc_first_line))
     47         else:
     48             return str(test)
     49 
     50     def startTest(self, test):
     51         super(TextTestResult, self).startTest(test)
     52         if self.showAll:
     53             self.stream.write(self.getDescription(test))
     54             self.stream.write(" ... ")
     55             self.stream.flush()
     56 
     57     def addSuccess(self, test):
     58         super(TextTestResult, self).addSuccess(test)
     59         if self.showAll:
     60             self.stream.writeln("ok")
     61         elif self.dots:
     62             self.stream.write('.')
     63             self.stream.flush()
     64 
     65     def addError(self, test, err):
     66         super(TextTestResult, self).addError(test, err)
     67         if self.showAll:
     68             self.stream.writeln("ERROR")
     69         elif self.dots:
     70             self.stream.write('E')
     71             self.stream.flush()
     72 
     73     def addFailure(self, test, err):
     74         super(TextTestResult, self).addFailure(test, err)
     75         if self.showAll:
     76             self.stream.writeln("FAIL")
     77         elif self.dots:
     78             self.stream.write('F')
     79             self.stream.flush()
     80 
     81     def addSkip(self, test, reason):
     82         super(TextTestResult, self).addSkip(test, reason)
     83         if self.showAll:
     84             self.stream.writeln("skipped {0!r}".format(reason))
     85         elif self.dots:
     86             self.stream.write("s")
     87             self.stream.flush()
     88 
     89     def addExpectedFailure(self, test, err):
     90         super(TextTestResult, self).addExpectedFailure(test, err)
     91         if self.showAll:
     92             self.stream.writeln("expected failure")
     93         elif self.dots:
     94             self.stream.write("x")
     95             self.stream.flush()
     96 
     97     def addUnexpectedSuccess(self, test):
     98         super(TextTestResult, self).addUnexpectedSuccess(test)
     99         if self.showAll:
    100             self.stream.writeln("unexpected success")
    101         elif self.dots:
    102             self.stream.write("u")
    103             self.stream.flush()
    104 
    105     def printErrors(self):
    106         if self.dots or self.showAll:
    107             self.stream.writeln()
    108         self.printErrorList('ERROR', self.errors)
    109         self.printErrorList('FAIL', self.failures)
    110 
    111     def printErrorList(self, flavour, errors):
    112         for test, err in errors:
    113             self.stream.writeln(self.separator1)
    114             self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
    115             self.stream.writeln(self.separator2)
    116             self.stream.writeln("%s" % err)
    117 
    118 
    119 class TextTestRunner(object):
    120     """A test runner class that displays results in textual form.
    121 
    122     It prints out the names of tests as they are run, errors as they
    123     occur, and a summary of the results at the end of the test run.
    124     """
    125     resultclass = TextTestResult
    126 
    127     def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1,
    128                  failfast=False, buffer=False, resultclass=None):
    129         self.stream = _WritelnDecorator(stream)
    130         self.descriptions = descriptions
    131         self.verbosity = verbosity
    132         self.failfast = failfast
    133         self.buffer = buffer
    134         if resultclass is not None:
    135             self.resultclass = resultclass
    136 
    137     def _makeResult(self):
    138         return self.resultclass(self.stream, self.descriptions, self.verbosity)
    139 
    140     def run(self, test):
    141         "Run the given test case or test suite."
    142         result = self._makeResult()
    143         registerResult(result)
    144         result.failfast = self.failfast
    145         result.buffer = self.buffer
    146         startTime = time.time()
    147         startTestRun = getattr(result, 'startTestRun', None)
    148         if startTestRun is not None:
    149             startTestRun()
    150         try:
    151             test(result)
    152         finally:
    153             stopTestRun = getattr(result, 'stopTestRun', None)
    154             if stopTestRun is not None:
    155                 stopTestRun()
    156         stopTime = time.time()
    157         timeTaken = stopTime - startTime
    158         result.printErrors()
    159         if hasattr(result, 'separator2'):
    160             self.stream.writeln(result.separator2)
    161         run = result.testsRun
    162         self.stream.writeln("Ran %d test%s in %.3fs" %
    163                             (run, run != 1 and "s" or "", timeTaken))
    164         self.stream.writeln()
    165 
    166         expectedFails = unexpectedSuccesses = skipped = 0
    167         try:
    168             results = map(len, (result.expectedFailures,
    169                                 result.unexpectedSuccesses,
    170                                 result.skipped))
    171         except AttributeError:
    172             pass
    173         else:
    174             expectedFails, unexpectedSuccesses, skipped = results
    175 
    176         infos = []
    177         if not result.wasSuccessful():
    178             self.stream.write("FAILED")
    179             failed, errored = map(len, (result.failures, result.errors))
    180             if failed:
    181                 infos.append("failures=%d" % failed)
    182             if errored:
    183                 infos.append("errors=%d" % errored)
    184         else:
    185             self.stream.write("OK")
    186         if skipped:
    187             infos.append("skipped=%d" % skipped)
    188         if expectedFails:
    189             infos.append("expected failures=%d" % expectedFails)
    190         if unexpectedSuccesses:
    191             infos.append("unexpected successes=%d" % unexpectedSuccesses)
    192         if infos:
    193             self.stream.writeln(" (%s)" % (", ".join(infos),))
    194         else:
    195             self.stream.write("\n")
    196         return result
    197