"""Monkey patch lame-o vanilla unittest with test skip feature. From the patch that was never applied (shameful!): http://bugs.python.org/issue1034053 """ import time, unittest class SkipException(Exception): pass def TestResult__init__(self): self.failures = [] self.errors = [] self.skipped = [] self.testsRun = 0 self.shouldStop = 0 unittest.TestResult.__init__ = TestResult__init__ def TestResult_addSkipped(self, test, err): """Called when a test is skipped. 'err' is a tuple of values as returned by sys.exc_info(). """ self.skipped.append((test, str(err[1]))) unittest.TestResult.addSkipped = TestResult_addSkipped def TestResult__repr__(self): return "<%s run=%i errors=%i failures=%i skipped=%i>" % ( unittest._strclass(self.__class__), self.testsRun, len(self.errors), len(self.failures), len(self.skipped)) unittest.TestResult.__repr__ = TestResult__repr__ class TestCase(unittest.TestCase): # Yuck, all of run has to be copied for this. # I don't care about wrapping setUp atm. def run(self, result=None): if result is None: result = self.defaultTestResult() result.startTest(self) # Support variable naming differences between 2.4 and 2.6 # Yay for silly variable hiding try: testMethodName = self.__testMethodName exc_info = self.__exc_info except AttributeError: testMethodName = self._testMethodName exc_info = self._exc_info testMethod = getattr(self, testMethodName) try: try: self.setUp() except KeyboardInterrupt: raise except: result.addError(self, exc_info()) return ok = False try: testMethod() ok = True except self.failureException: result.addFailure(self, exc_info()) except SkipException: result.addSkipped(self, exc_info()) except KeyboardInterrupt: raise except: result.addError(self, exc_info()) try: self.tearDown() except KeyboardInterrupt: raise except: result.addError(self, exc_info()) ok = False if ok: result.addSuccess(self) finally: result.stopTest(self) def skip(self, msg=None): """Skip the test, with the given message.""" raise SkipException(msg) def skipIf(self, expr, msg=None): """Skip the test if the expression is true.""" if expr: raise SkipException(msg) def _TextTestResult_addSkipped(self, test, err): unittest.TestResult.addSkipped(self, test, err) if self.showAll: msg = str(err[1]) if msg: msg = " (" + msg + ")" self.stream.writeln("SKIPPED" + msg) elif self.dots: self.stream.write('S') unittest._TextTestResult.addSkipped = _TextTestResult_addSkipped # Bah def TextTestRunner_run(self, test): "Run the given test case or test suite." result = self._makeResult() startTime = time.time() test(result) stopTime = time.time() timeTaken = stopTime - startTime result.printErrors() self.stream.writeln(result.separator2) run = result.testsRun self.stream.writeln("Ran %d test%s in %.3fs" % (run, run != 1 and "s" or "", timeTaken)) self.stream.writeln() if not result.wasSuccessful(): self.stream.write("FAILED (") failed, errored, skipped = map( len, (result.failures, result.errors, result.skipped)) if failed: self.stream.write("failures=%d" % failed) if errored: if failed: self.stream.write(", ") self.stream.write("errors=%d" % errored) if skipped: self.stream.write(", skipped=%d" % skipped) self.stream.writeln(")") else: if result.skipped: self.stream.writeln( "OK (skipped=%d)" % len(result.skipped)) else: self.stream.writeln("OK") return result unittest.TextTestRunner.run = TextTestRunner_run