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