runner.py 6.4 KB

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