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
|
"""
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.2 - removed unused import that failed on Python 2.6
0.1 - initial release
"""
from unittest.runner import TextTestRunner, TextTestResult
__version__ = "0.2"
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)
|