--- /dev/null
+"""Generic test runner.
+
+This module scans for filenames begining with test_ and runs the tests
+in them. It is less noisy than the default Python test runners.
+"""
+
+from __future__ import division
+from __future__ import print_function
+
+import glob
+import os
+import sys
+import unittest
+
+from unittest import TestCase
+
+suites = []
+add = suites.append
+
+for name in glob.glob(os.path.join(os.path.dirname(__file__), "test_*.py")):
+ module = "tests." + os.path.basename(name)
+ __import__(module[:-3], {}, {}, [])
+
+class Result(unittest.TestResult):
+
+ separator1 = '=' * 70
+ separator2 = '-' * 70
+
+ def addSuccess(self, test):
+ unittest.TestResult.addSuccess(self, test)
+ sys.stdout.write('.')
+
+ def addError(self, test, err):
+ unittest.TestResult.addError(self, test, err)
+ sys.stdout.write('E')
+
+ def addFailure(self, test, err):
+ unittest.TestResult.addFailure(self, test, err)
+ sys.stdout.write('F')
+
+ def printErrors(self):
+ succ = self.testsRun - (len(self.errors) + len(self.failures))
+ v = "%3d" % succ
+ count = 50 - self.testsRun
+ sys.stdout.write((" " * count) + v + "\n")
+ self.printErrorList('ERROR', self.errors)
+ self.printErrorList('FAIL', self.failures)
+
+ def printErrorList(self, flavour, errors):
+ for test, err in errors:
+ sys.stdout.write(self.separator1 + "\n")
+ sys.stdout.write("%s: %s\n" % (flavour, str(test)))
+ sys.stdout.write(self.separator2 + "\n")
+ sys.stdout.write("%s\n" % err)
+
+class Runner(object):
+ def run(self, test):
+ suite = unittest.makeSuite(test)
+ pref = '%s (%d): ' % (test.__name__, len(suite._tests))
+ print(pref + " " * (25 - len(pref)), end=" ")
+ result = Result()
+ suite(result)
+ result.printErrors()
+ return bool(result.failures + result.errors)
+
+def unit(run=[]):
+ runner = Runner()
+ failures = False
+ for test in suites:
+ if not run or test.__name__ in run or test.__name__.lstrip("T") in run:
+ failures |= runner.run(test)
+ return failures