run.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #!/usr/bin/python -O
  2. import curses
  3. import importlib
  4. import sys
  5. import unittest
  6. test_order = [
  7. 'qubes.tests.events',
  8. 'qubes.tests.vm.init',
  9. 'qubes.tests.vm.qubesvm',
  10. 'qubes.tests.init'
  11. ]
  12. sys.path.insert(0, '../../')
  13. class ANSIColor(dict):
  14. def __init__(self):
  15. super(ANSIColor, self).__init__()
  16. try:
  17. curses.setupterm()
  18. except curses.error:
  19. return
  20. self['black'] = curses.tparm(curses.tigetstr('setaf'), 0)
  21. self['red'] = curses.tparm(curses.tigetstr('setaf'), 1)
  22. self['green'] = curses.tparm(curses.tigetstr('setaf'), 2)
  23. self['yellow'] = curses.tparm(curses.tigetstr('setaf'), 3)
  24. self['blue'] = curses.tparm(curses.tigetstr('setaf'), 4)
  25. self['magenta'] = curses.tparm(curses.tigetstr('setaf'), 5)
  26. self['cyan'] = curses.tparm(curses.tigetstr('setaf'), 6)
  27. self['white'] = curses.tparm(curses.tigetstr('setaf'), 7)
  28. self['bold'] = curses.tigetstr('bold')
  29. self['normal'] = curses.tigetstr('sgr0')
  30. def __missing__(self, key):
  31. return ''
  32. class ANSITestResult(unittest.TestResult):
  33. '''A test result class that can print colourful text results to a stream.
  34. Used by TextTestRunner. This is a lightly rewritten unittest.TextTestResult.
  35. '''
  36. separator1 = unittest.TextTestResult.separator1
  37. separator2 = unittest.TextTestResult.separator2
  38. def __init__(self, stream, descriptions, verbosity):
  39. super(ANSITestResult, self).__init__(stream, descriptions, verbosity)
  40. self.stream = stream
  41. self.showAll = verbosity > 1
  42. self.dots = verbosity == 1
  43. self.descriptions = descriptions
  44. self.color = ANSIColor()
  45. def _fmtexc(self, err):
  46. s = str(err[1])
  47. if s:
  48. return '{bold}{}:{normal} {!s}'.format(
  49. err[0].__name__, err[1], **self.color)
  50. else:
  51. return '{bold}{}{normal}'.format(err[0].__name__, **self.color)
  52. def getDescription(self, test):
  53. teststr = str(test).split('/')
  54. teststr[-1] = '{bold}{}{normal}'.format(teststr[-1], **self.color)
  55. teststr = '/'.join(teststr)
  56. doc_first_line = test.shortDescription()
  57. if self.descriptions and doc_first_line:
  58. return '\n'.join((teststr, ' {}'.format(
  59. doc_first_line, **self.color)))
  60. else:
  61. return teststr
  62. def startTest(self, test):
  63. super(ANSITestResult, self).startTest(test)
  64. if self.showAll:
  65. self.stream.write(self.getDescription(test))
  66. self.stream.write(' ... ')
  67. self.stream.flush()
  68. def addSuccess(self, test):
  69. super(ANSITestResult, self).addSuccess(test)
  70. if self.showAll:
  71. self.stream.writeln('{green}ok{normal}'.format(**self.color))
  72. elif self.dots:
  73. self.stream.write('.')
  74. self.stream.flush()
  75. def addError(self, test, err):
  76. super(ANSITestResult, self).addError(test, err)
  77. if self.showAll:
  78. self.stream.writeln('{red}{bold}ERROR{normal} ({})'.format(
  79. self._fmtexc(err), **self.color))
  80. elif self.dots:
  81. self.stream.write('{red}{bold}E{normal}'.format(**self.color))
  82. self.stream.flush()
  83. def addFailure(self, test, err):
  84. super(ANSITestResult, self).addFailure(test, err)
  85. if self.showAll:
  86. self.stream.writeln('{red}FAIL{normal}'.format(**self.color))
  87. elif self.dots:
  88. self.stream.write('{red}F{normal}'.format(**self.color))
  89. self.stream.flush()
  90. def addSkip(self, test, reason):
  91. super(ANSITestResult, self).addSkip(test, reason)
  92. if self.showAll:
  93. self.stream.writeln('{cyan}skipped{normal} ({})'.format(
  94. reason, **self.color))
  95. elif self.dots:
  96. self.stream.write('{cyan}s{normal}'.format(**self.color))
  97. self.stream.flush()
  98. def addExpectedFailure(self, test, err):
  99. super(ANSITestResult, self).addExpectedFailure(test, err)
  100. if self.showAll:
  101. self.stream.writeln('{yellow}expected failure{normal}'.format(
  102. **self.color))
  103. elif self.dots:
  104. self.stream.write('{yellow}x{normal}'.format(**self.color))
  105. self.stream.flush()
  106. def addUnexpectedSuccess(self, test):
  107. super(ANSITestResult, self).addUnexpectedSuccess(test)
  108. if self.showAll:
  109. self.stream.writeln(
  110. '{yellow}{bold}unexpected success{normal}'.format(**self.color))
  111. elif self.dots:
  112. self.stream.write('{yellow}{bold}u{normal}'.format(**self.color))
  113. self.stream.flush()
  114. def printErrors(self):
  115. if self.dots or self.showAll:
  116. self.stream.writeln()
  117. self.printErrorList(
  118. '{red}{bold}ERROR{normal}'.format(**self.color), self.errors)
  119. self.printErrorList(
  120. '{red}FAIL{normal}'.format(**self.color), self.failures)
  121. def printErrorList(self, flavour, errors):
  122. for test, err in errors:
  123. self.stream.writeln(self.separator1)
  124. self.stream.writeln('%s: %s' % (flavour,self.getDescription(test)))
  125. self.stream.writeln(self.separator2)
  126. self.stream.writeln('%s' % err)
  127. def demo(verbosity=2):
  128. import qubes.tests
  129. class TC_Demo(qubes.tests.QubesTestCase):
  130. '''Demo class'''
  131. def test_0_success(self):
  132. '''Demo test (success)'''
  133. pass
  134. def test_1_error(self):
  135. '''Demo test (error)'''
  136. raise Exception()
  137. def test_2_failure(self):
  138. '''Demo test (failure)'''
  139. self.fail('boo')
  140. def test_3_skip(self):
  141. '''Demo test (skipped by call to self.skipTest())'''
  142. self.skipTest('skip')
  143. @unittest.skip(None)
  144. def test_4_skip_decorator(self):
  145. '''Demo test (skipped by decorator)'''
  146. pass
  147. @unittest.expectedFailure
  148. def test_5_expected_failure(self):
  149. '''Demo test (expected failure)'''
  150. self.fail()
  151. @unittest.expectedFailure
  152. def test_6_unexpected_success(self):
  153. '''Demo test (unexpected success)'''
  154. pass
  155. suite = unittest.TestLoader().loadTestsFromTestCase(TC_Demo)
  156. runner = unittest.TextTestRunner(stream=sys.stdout, verbosity=verbosity)
  157. runner.resultclass = ANSITestResult
  158. return runner.run(suite).wasSuccessful()
  159. def main():
  160. suite = unittest.TestSuite()
  161. loader = unittest.TestLoader()
  162. for modname in test_order:
  163. module = importlib.import_module(modname)
  164. suite.addTests(loader.loadTestsFromModule(module))
  165. runner = unittest.TextTestRunner(stream=sys.stdout, verbosity=2)
  166. runner.resultclass = ANSITestResult
  167. return runner.run(suite).wasSuccessful()
  168. if __name__ == '__main__':
  169. sys.exit(not main())