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
|
"""
Format unittest results in Test Anything Protocol (TAP).
http://testanything.org/tap-version-13-specification.html
Public domain work by:
anatoly techtonik <techtonik@gmail.com>
Changes:
0.3 - fixed used imports that failed on Python 2.6
0.2 - removed unused import that failed on Python 2.6
0.1 - initial release
"""
__version__ = "0.3"
from unittest import TextTestRunner
try:
from unittest import TextTestResult
except ImportError:
# Python 2.6
from unittest import _TextTestResult as TextTestResult
class TAPTestResult(TextTestResult):
def _process(self, test, msg, failtype = None, directive = None):
""" increase the counter, format and output TAP info """
# counterhack: increase test counter
test.suite.tap_counter += 1
msg = "%s %d" % (msg, test.suite.tap_counter)
if "not" not in msg:
msg += " " # justify
self.stream.write("%s - " % msg)
if failtype:
self.stream.write("%s - " % failtype)
self.stream.write("%s" % test.__class__.__name__)
self.stream.write(".%s" % test._testMethodName)
if directive:
self.stream.write(directive)
self.stream.write("\n")
# [ ] write test __doc__ (if exists) in comment
self.stream.flush()
def addSuccess(self, test):
super(TextTestResult, self).addSuccess(test)
self._process(test, "ok")
def addFailure(self, test, err):
super(TextTestResult, self).addFailure(test, err)
self._process(test, "not ok", "FAIL")
# [ ] add structured data about assertion
def addError(self, test, err):
super(TextTestResult, self).addError(test, err)
self._process(test, "not ok", "ERROR")
# [ ] add structured data about exception
def addSkip(self, test, reason):
super(TextTestResult, self).addSkip(test, reason)
self._process(test, "ok", directive=(" # SKIP %s" % reason))
def addExpectedFailure(self, test, err):
super(TextTestResult, self).addExpectedFailure(test, err)
self._process(test, "not ok", directive=(" # TODO"))
def addUnexpectedSuccess(self, test):
super(TextTestResult, self).addUnexpectedSuccess(test)
self._process(test, "not ok", "FAIL (unexpected success)")
"""
def printErrors(self):
def printErrorList(self, flavour, errors):
"""
class TAPTestRunner(TextTestRunner):
resultclass = TAPTestResult
def run(self, test):
self.stream.write("TAP version 13\n")
# [ ] add commented block with test suite __doc__
# [ ] check call with a single test
# if isinstance(test, suite.TestSuite):
self.stream.write("1..%s\n" % len(list(test)))
# counterhack: inject test counter into test suite
test.tap_counter = 0
# counterhack: inject reference to suite into each test case
for case in test:
case.suite = test
return super(TAPTestRunner, self).run(test)
if __name__ == "__main__":
import sys
import unittest
class Test(unittest.TestCase):
def test_ok(self):
pass
def test_fail(self):
self.assertTrue(False)
def test_error(self):
bad_symbol
@unittest.skip("skipin'")
def test_skip(self):
pass
@unittest.expectedFailure
def test_not_ready(self):
self.fail()
@unittest.expectedFailure
def test_invalid_fail_mark(self):
pass
def test_another_ok(self):
pass
suite = unittest.TestSuite([
Test('test_ok'),
Test('test_fail'),
Test('test_error'),
Test('test_skip'),
Test('test_not_ready'),
Test('test_invalid_fail_mark'),
Test('test_another_ok')
])
if not TAPTestRunner().run(suite).wasSuccessful():
sys.exit(1)
|