1# Lint as: python2, python3 2"""Monkey patch lame-o vanilla unittest with test skip feature. 3 4From the patch that was never applied (shameful!): 5http://bugs.python.org/issue1034053 6""" 7 8from __future__ import absolute_import 9from __future__ import division 10from __future__ import print_function 11import time, unittest 12from six.moves import map 13 14 15class SkipException(Exception): 16 pass 17 18 19def TestResult__init__(self): 20 self.failures = [] 21 self.errors = [] 22 self.skipped = [] 23 self.testsRun = 0 24 self.shouldStop = 0 25 26unittest.TestResult.__init__ = TestResult__init__ 27 28 29def TestResult_addSkipped(self, test, err): 30 """Called when a test is skipped. 31 32 'err' is a tuple of values as returned by sys.exc_info(). 33 """ 34 self.skipped.append((test, str(err[1]))) 35 36unittest.TestResult.addSkipped = TestResult_addSkipped 37 38 39def TestResult__repr__(self): 40 return "<%s run=%i errors=%i failures=%i skipped=%i>" % ( 41 unittest._strclass(self.__class__), self.testsRun, 42 len(self.errors), len(self.failures), len(self.skipped)) 43 44unittest.TestResult.__repr__ = TestResult__repr__ 45 46 47class TestCase(unittest.TestCase): 48 # Yuck, all of run has to be copied for this. 49 # I don't care about wrapping setUp atm. 50 def run(self, result=None): 51 if result is None: result = self.defaultTestResult() 52 result.startTest(self) 53 # Support variable naming differences between 2.4 and 2.6 54 # Yay for silly variable hiding 55 try: 56 testMethodName = self.__testMethodName 57 exc_info = self.__exc_info 58 except AttributeError: 59 testMethodName = self._testMethodName 60 exc_info = self._exc_info 61 62 testMethod = getattr(self, testMethodName) 63 64 try: 65 try: 66 self.setUp() 67 except KeyboardInterrupt: 68 raise 69 except: 70 result.addError(self, exc_info()) 71 return 72 73 ok = False 74 try: 75 testMethod() 76 ok = True 77 except self.failureException: 78 result.addFailure(self, exc_info()) 79 except SkipException: 80 result.addSkipped(self, exc_info()) 81 except KeyboardInterrupt: 82 raise 83 except: 84 result.addError(self, exc_info()) 85 86 try: 87 self.tearDown() 88 except KeyboardInterrupt: 89 raise 90 except: 91 result.addError(self, exc_info()) 92 ok = False 93 if ok: result.addSuccess(self) 94 finally: 95 result.stopTest(self) 96 97 98 def skip(self, msg=None): 99 """Skip the test, with the given message.""" 100 raise SkipException(msg) 101 102 103 def skipIf(self, expr, msg=None): 104 """Skip the test if the expression is true.""" 105 if expr: 106 raise SkipException(msg) 107 108 109def _TextTestResult_addSkipped(self, test, err): 110 unittest.TestResult.addSkipped(self, test, err) 111 if self.showAll: 112 msg = str(err[1]) 113 if msg: 114 msg = " (" + msg + ")" 115 self.stream.writeln("SKIPPED" + msg) 116 elif self.dots: 117 self.stream.write('S') 118 119unittest._TextTestResult.addSkipped = _TextTestResult_addSkipped 120 121 122# Bah 123def TextTestRunner_run(self, test): 124 "Run the given test case or test suite." 125 result = self._makeResult() 126 startTime = time.time() 127 test(result) 128 stopTime = time.time() 129 timeTaken = stopTime - startTime 130 result.printErrors() 131 self.stream.writeln(result.separator2) 132 run = result.testsRun 133 self.stream.writeln("Ran %d test%s in %.3fs" % 134 (run, run != 1 and "s" or "", timeTaken)) 135 self.stream.writeln() 136 if not result.wasSuccessful(): 137 self.stream.write("FAILED (") 138 failed, errored, skipped = list(map( 139 len, (result.failures, result.errors, result.skipped))) 140 if failed: 141 self.stream.write("failures=%d" % failed) 142 if errored: 143 if failed: self.stream.write(", ") 144 self.stream.write("errors=%d" % errored) 145 if skipped: 146 self.stream.write(", skipped=%d" % skipped) 147 self.stream.writeln(")") 148 else: 149 if result.skipped: 150 self.stream.writeln( 151 "OK (skipped=%d)" % len(result.skipped)) 152 else: 153 self.stream.writeln("OK") 154 return result 155 156unittest.TextTestRunner.run = TextTestRunner_run 157