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)
|