1 # SPDX-License-Identifier: BSD-2-Clause
3 # Copyright (c) 2016, Matt Layman
6 from unittest
import TextTestResult
, TextTestRunner
7 from unittest
.runner
import _WritelnDecorator
10 from tap
import formatter
11 from tap
.i18n
import _
12 from tap
.tracker
import Tracker
15 class TAPTestResult(TextTestResult
):
19 def __init__(self
, stream
, descriptions
, verbosity
):
20 super(TAPTestResult
, self
).__init
__(stream
, descriptions
, verbosity
)
22 def stopTestRun(self
):
23 """Once the test run is complete, generate each of the TAP files."""
24 super(TAPTestResult
, self
).stopTestRun()
25 self
.tracker
.generate_tap_reports()
27 def addError(self
, test
, err
):
28 super(TAPTestResult
, self
).addError(test
, err
)
29 diagnostics
= formatter
.format_exception(err
)
30 self
.tracker
.add_not_ok(
31 self
._cls
_name
(test
), self
._description
(test
),
32 diagnostics
=diagnostics
)
34 def addFailure(self
, test
, err
):
35 super(TAPTestResult
, self
).addFailure(test
, err
)
36 diagnostics
= formatter
.format_exception(err
)
37 self
.tracker
.add_not_ok(
38 self
._cls
_name
(test
), self
._description
(test
),
39 diagnostics
=diagnostics
)
41 def addSuccess(self
, test
):
42 super(TAPTestResult
, self
).addSuccess(test
)
43 self
.tracker
.add_ok(self
._cls
_name
(test
), self
._description
(test
))
45 def addSkip(self
, test
, reason
):
46 super(TAPTestResult
, self
).addSkip(test
, reason
)
47 self
.tracker
.add_skip(
48 self
._cls
_name
(test
), self
._description
(test
), reason
)
50 def addExpectedFailure(self
, test
, err
):
51 super(TAPTestResult
, self
).addExpectedFailure(test
, err
)
52 diagnostics
= formatter
.format_exception(err
)
53 self
.tracker
.add_not_ok(
54 self
._cls
_name
(test
), self
._description
(test
),
55 _('(expected failure)'), diagnostics
=diagnostics
)
57 def addUnexpectedSuccess(self
, test
):
58 super(TAPTestResult
, self
).addUnexpectedSuccess(test
)
59 self
.tracker
.add_ok(self
._cls
_name
(test
), self
._description
(test
),
60 _('(unexpected success)'))
62 def _cls_name(self
, test
):
63 return test
.__class
__.__name
__
65 def _description(self
, test
):
68 return self
.FORMAT
.format(
69 method_name
=str(test
),
70 short_description
=test
.shortDescription() or '')
73 'Bad format string: {format}\n'
74 'Replacement options are: {{short_description}} and '
75 '{{method_name}}').format(format
=self
.FORMAT
))
77 return test
.shortDescription() or str(test
)
80 # TODO: 2016-7-30 mblayman - Since the 2.6 signature is no longer relevant,
81 # check the possibility of removing the module level scope.
83 # Module level state stinks, but this is the only way to keep compatibility
84 # with Python 2.6. The best place for the tracker is as an instance variable
85 # on the runner, but __init__ is so different that it is not easy to create
86 # a runner that satisfies every supported Python version.
90 class TAPTestRunner(TextTestRunner
):
91 """A test runner that will behave exactly like TextTestRunner and will
92 additionally generate TAP files for each test case"""
94 resultclass
= TAPTestResult
96 def set_stream(self
, streaming
):
97 """Set the streaming boolean option to stream TAP directly to stdout.
99 The test runner default output will be suppressed in favor of TAP.
101 self
.stream
= _WritelnDecorator(open(os
.devnull
, 'w'))
102 _tracker
.streaming
= streaming
103 _tracker
.stream
= sys
.stdout
105 def _makeResult(self
):
106 result
= self
.resultclass(
107 self
.stream
, self
.descriptions
, self
.verbosity
)
108 result
.tracker
= _tracker
112 def set_outdir(cls
, outdir
):
113 """Set the output directory so that TAP files are written to the
114 specified outdir location.
116 # Blame the lack of unittest extensibility for this hacky method.
117 _tracker
.outdir
= outdir
120 def set_combined(cls
, combined
):
121 """Set the tracker to use a single output file."""
122 _tracker
.combined
= combined
125 def set_header(cls
, header
):
126 """Set the header display flag."""
127 _tracker
.header
= header
130 def set_format(cls
, fmt
):
131 """Set the format of each test line.
133 The format string can use:
134 * {method_name}: The test method name
135 * {short_description}: The test's docstring short description
137 TAPTestResult
.FORMAT
= fmt
This page took 0.031521 seconds and 4 git commands to generate.