import os import sys import time import unittest class TextTestRunner(unittest.TextTestRunner): """This is a wrapper class used to minimize the amount of blank lines printed to stdout. The method ``run`` is modified and it's original source is in Python Standard Library's ``unittest`` module.""" def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1, color=True): unittest.TextTestRunner.__init__(self, stream, descriptions, verbosity) self.color = color def run(self, test): "Run the given test case or test suite." result = self._makeResult() result.failfast = getattr(self, 'failfast', None) result.buffer = getattr(self, 'buffer', None) startTime = time.time() startTestRun = getattr(result, 'startTestRun', None) if startTestRun is not None: startTestRun() try: test(result) finally: stopTestRun = getattr(result, 'stopTestRun', None) if stopTestRun is not None: stopTestRun() stopTime = time.time() timeTaken = stopTime - startTime result.printErrors() run = result.testsRun msg = 'Ran %d test%s in %.3fs ' self.stream.write(msg % (run, run != 1 and 's' or '', timeTaken)) expectedFails = unexpectedSuccesses = skipped = 0 try: results = map(len, (result.expectedFailures, result.unexpectedSuccesses, result.skipped)) except AttributeError: pass else: expectedFails, unexpectedSuccesses, skipped = results infos = [] if not result.wasSuccessful(): if self.color: msg = '\033[0;31mFAILED\033[1;m' else: msg = 'FAILED' self.stream.write(msg) failed, errored = map(len, (result.failures, result.errors)) if failed: if self.color: msg = 'failures=\033[1;31m%d\033[1;m' else: msg = 'failures=%d' infos.append(msg % failed) if errored: if self.color: msg = 'errors=\033[1;31m%d\033[1;m' else: msg = 'errors=%d' infos.append(msg % errored) else: if self.color: msg = '\033[0;32mOK\033[0;m' else: msg = 'OK' self.stream.write(msg) if skipped: if self.color: msg = 'skipped=\033[1;33m%d\033[1;m' else: msg = 'skipped=%d' infos.append(msg % skipped) if expectedFails: infos.append('expected failures=%d' % expectedFails) if unexpectedSuccesses: infos.append('unexpected successes=%d' % unexpectedSuccesses) if infos: self.stream.writeln(' (%s)' % (', '.join(infos),)) else: self.stream.write('\n') return result def main(tests, verbose=0, color=True): suites = [] # Dynamic load the requested module containing the test cases. for testfile in tests: module_dir, module_file = os.path.split(testfile) module_name, module_ext = os.path.splitext(module_file) # XXX: this looks really hacky, so cleanup is necessary. module_obj = __import__(module_dir.replace('/', '.'), fromlist=[module_name]) module_obj.__file__ = testfile globals()[module_name] = module_obj # Start the test runner and display the results to stdout. container = module_obj.__dict__[module_name] class_parts = module_name[5:].split('_') class_name = 'Test' + ''.join([p.capitalize() for p in class_parts]) testcase = container.__dict__[class_name] suites += [unittest.TestLoader().loadTestsFromTestCase(testcase)] # Create the text runner and execute the tests. runner = TextTestRunner(verbosity=verbose, color=color) runner.run(unittest.TestSuite(suites))