]> git.parisson.com Git - timeside.git/commitdiff
add custom unittest runner (grouping by test cases) and a custom base TestCase
authorOlivier Guilyardi <olivier@samalyse.com>
Fri, 19 Feb 2010 17:40:36 +0000 (17:40 +0000)
committerOlivier Guilyardi <olivier@samalyse.com>
Fri, 19 Feb 2010 17:40:36 +0000 (17:40 +0000)
tests/__init__.py

index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2a6b9dbc466558037d79fa771965e7b62cde8c58 100644 (file)
@@ -0,0 +1,140 @@
+
+import unittest
+import sys
+import time
+
+class TestCase(unittest.TestCase):
+
+    def assertSameList(self, list1, list2):
+        "Test that two lists contain the same elements, in any order"
+        if len(list1) != len(list2):
+            self.fail("Lists length differ : %d != %d" % (len(list1), len(list2)))
+
+        for item in list1:
+            if not item in list2:
+                self.fail("%s is not in list2" % str(item))
+
+        for item in list2:
+            if not item in list1:
+                self.fail("%s is not in list1" % str(item))
+        
+class _TextTestResult(unittest.TestResult):
+    """A test result class that can print formatted text results to a stream.
+
+    Used by TextTestRunner.
+    """
+    separator1 = '=' * 70
+    separator2 = '-' * 70
+
+    def __init__(self, stream, descriptions, verbosity):
+        unittest.TestResult.__init__(self)
+        self.stream = stream
+        self.showAll = verbosity > 1
+        self.dots = verbosity == 1
+        self.descriptions = descriptions
+        self.currentTestCase = None
+
+    def getDescription(self, test):
+        if self.descriptions:
+            return test.shortDescription() or str(test)
+        else:
+            return str(test)
+
+    def startTest(self, test):
+        unittest.TestResult.startTest(self, test)
+        if self.showAll:
+            if self.currentTestCase != test.__class__:
+                self.currentTestCase = test.__class__
+                self.stream.writeln()
+                self.stream.writeln("[%s]" % self.currentTestCase.__name__)
+            self.stream.write("  " + self.getDescription(test))
+            self.stream.write(" ... ")
+
+    def addSuccess(self, test):
+        unittest.TestResult.addSuccess(self, test)
+        if self.showAll:
+            self.stream.writeln("ok")
+        elif self.dots:
+            self.stream.write('.')
+
+    def addError(self, test, err):
+        unittest.TestResult.addError(self, test, err)
+        if self.showAll:
+            self.stream.writeln("ERROR")
+        elif self.dots:
+            self.stream.write('E')
+
+    def addFailure(self, test, err):
+        unittest.TestResult.addFailure(self, test, err)
+        if self.showAll:
+            self.stream.writeln("FAIL")
+        elif self.dots:
+            self.stream.write('F')
+
+    def printErrors(self):
+        if self.dots or self.showAll:
+            self.stream.writeln()
+        self.printErrorList('ERROR', self.errors)
+        self.printErrorList('FAIL', self.failures)
+
+    def printErrorList(self, flavour, errors):
+        for test, err in errors:
+            self.stream.writeln(self.separator1)
+            self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
+            self.stream.writeln(self.separator2)
+            self.stream.writeln("%s" % err)
+
+
+class _WritelnDecorator:
+    """Used to decorate file-like objects with a handy 'writeln' method"""
+    def __init__(self,stream):
+        self.stream = stream
+
+    def __getattr__(self, attr):
+        return getattr(self.stream,attr)
+
+    def writeln(self, arg=None):
+        if arg: self.write(arg)
+        self.write('\n') # text-mode streams translate to \r\n if needed
+
+class TestRunner:
+    """A test runner class that displays results in textual form.
+
+    It prints out the names of tests as they are run, errors as they
+    occur, and a summary of the results at the end of the test run.
+    """
+    def __init__(self, stream=sys.stderr, descriptions=1, verbosity=2):
+        self.stream = _WritelnDecorator(stream)
+        self.descriptions = descriptions
+        self.verbosity = verbosity
+
+    def _makeResult(self):
+        return _TextTestResult(self.stream, self.descriptions, self.verbosity)
+
+    def 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 = map(len, (result.failures, result.errors))
+            if failed:
+                self.stream.write("failures=%d" % failed)
+            if errored:
+                if failed: self.stream.write(", ")
+                self.stream.write("errors=%d" % errored)
+            self.stream.writeln(")")
+        else:
+            self.stream.writeln("OK")
+        return result
+
+