File: testRunner.py

package info (click to toggle)
sanlock 2.2-2
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 1,124 kB
  • ctags: 1,917
  • sloc: ansic: 12,971; python: 896; sh: 440; makefile: 227
file content (171 lines) | stat: -rw-r--r-- 5,534 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import sys
from unittest import TestResult
from fnmatch import fnmatch
import traceback
from itertools import chain, ifilter

from enum import Enum

eColors = Enum(
    Green = '\033[92m',
    Yellow = '\033[93m',
    Red = '\033[91m',
    ENDC = '\033[0m'
    )

_faultSeperator = "-" * 80

def _formatTestFault(test, err, faultTypeName):
    res = "%s\n%s: %s :\n%s\n" % (_faultSeperator, faultTypeName, test.id(), err)
    return res


class _TextTestResult(TestResult):
    """
    A better way to display test results in in the terminal.

    Assumes correct an linear execution per test.
    """
    def __init__(self, stream, verbosity = 1, logging=False):
        TestResult.__init__(self)
        self._stream = stream
        self._verbosity = verbosity
        self._logging = logging

    def _writeToStream(self, msg, color=None):
        stream = self._stream

        #Make sure color is a color
        if color != None:
            color = eColors.parse(color)

        writeColor = False
        try:
            writeColor = (color != None and stream.isatty())
        except AttributeError: #A strem might no implement isatty
            pass

        if writeColor:
            msg = color + msg + eColors.ENDC

        stream.write(msg)
        stream.flush()

    def startTest(self, test):
        TestResult.startTest(self, test)
        self._writeToStream("\t%s: " % test.id())
        if self._logging:
            self._writeToStream("\n")

    def addSuccess(self, test):
        TestResult.addSuccess(self, test)
        if self._logging:
            self._writeToStream("\tResult: ")
        self._writeToStream("OK", eColors.Green)

    def addError(self, test, err):
        testname = test.id().split(".")[-1]
        tb = err[2]
        stack = traceback.extract_tb(tb)
        for frame in stack:
            fname = frame[2]
            if fname == testname:
                if self._logging:
                    self._writeToStream("\tResult: ")
                self._writeToStream("Test ERROR", eColors.Yellow)
                break
            if fname == "setUp":
                if self._logging:
                    self._writeToStream("\tResult: ")
                self._writeToStream("SetUp ERROR", eColors.Yellow)
                break
            if fname == "tearDown":
                #If test succeded but tear down failed the result should
                #still be that the test failed. So it's my resposibility
                #to display thet only the 'test' part of the test passed. (Confused yet?)
                faults = chain(self.failures, self.errors)
                testFaults = ifilter(lambda item: item[0] == test, faults)
                hasFailed = (sum(1 for u in testFaults) > 0)
                if not hasFailed:
                    if self._logging:
                        self._writeToStream("\tResult: ")
                    self._writeToStream("PASSED", eColors.Green)

                self._writeToStream(", ")
                self._writeToStream("Tear Down ERROR", eColors.Yellow)
                break

        TestResult.addError(self, test, err)

    def addFailure(self, test, err):
        if self._logging:
            self._writeToStream("\tResult: ")
        TestResult.addFailure(self, test, err)
        self._writeToStream("FAIL", eColors.Red)

    def stopTest(self, test):
        TestResult.stopTest(self, test)
        self._writeToStream("\n")
        self.printTestErrLog(test, 3)

    def printTestErrLog(self, test, minVerbosity):
        if self._verbosity < minVerbosity:
            return

        for fTest, err in self.failures:
            if test == fTest:
               self._writeToStream( _formatTestFault(test, err, "FAILURE"))
        for eTest, err in self.errors:
            if test == eTest:
               self._writeToStream( _formatTestFault(test, err, "ERROR"))

class TestRunner(object):
    """
    A test runner that is better then the default :class:`unittest.TextTestRunner`.
    Gives prettier output.
    """
    def __init__(self, stream = sys.stderr, verbosity=1, filter="*", logging=False):
        self._verbosity = verbosity
        self._stream = stream
        self._filter = filter
        self._logging = logging

    def run(self, suite):
        """
        Run a test.
        """
        stream = self._stream
        results = _TextTestResult(stream, self._verbosity, self._logging)

        #Parse filter
        filter = self._filter
        filterIfMatchIs = True
        if filter.startswith("^"):
            filterIfMatchIs = False
            filter = filter[1:]
        filter = filter.replace("\\^", "^") #So you could escape ^. For completeness.
        filter = filter.replace("\\\\", "\\")

        for test in suite:
            if not (fnmatch(test.id(), filter) == filterIfMatchIs):
                continue

            test.run(result = results)

        if results.wasSuccessful():
            msg = "All Good!"
        else:
            msg = "Failed (failures=%d, errors=%d)." % (len(results.failures), len(results.errors))
        sep = "*" * (len(msg) + 4) + "\n"
        stream.write(sep)
        stream.write("* " + msg + " *" + "\n")
        stream.write(sep)

        if self._verbosity == 2:
            for test, err in results.failures:
                stream.write(_formatTestFault(test, err, "FAILURE"))
            for test, err in results.errors:
                stream.write(_formatTestFault(test, err, "ERROR"))

        stream.flush()
        return results