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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
|
# Copyright (c) 2015 testtools developers. See LICENSE for details.
"""Interfaces used within testtools."""
from zope.interface import Attribute, Interface
class IRunnable(Interface):
"""A thing that a test runner can run."""
def __call__(result=None):
"""Equivalent to ``run``."""
def countTestCases():
"""Return the number of tests this represents."""
def debug():
pass
def run(result=None):
"""Run the test."""
class ITestSuite(IRunnable):
"""A suite of tests."""
def __iter__():
"""Iterate over the IRunnables in suite."""
class ITestCase(IRunnable):
"""An individual test case."""
def __str__():
"""Return a short, human-readable description."""
def id():
"""A unique identifier."""
def shortDescription(self):
"""Return a short, human-readable description."""
class IExceptionHandler(Interface):
"""Handle an exception from user code."""
def __call__(test_case, test_result, exception_value):
"""Handle an exception raised from user code.
:param TestCase test_case: The test that raised the exception.
:param TestResult test_result: Where to report the result to.
:param Exception exception_value: The raised exception.
"""
class IRunTestFactory(Interface):
"""Create a ``RunTest`` object."""
def __call__(test_case, exception_handlers, last_resort=None):
"""Construct and return a ``RunTest``.
:param ITestCase+ITestCaseStrategy test_case: The test case to run.
:param exception_handlers: List of (exception_type, IExceptionHandler).
This list can be mutated any time.
:param IExceptionHandler last_resort: exception handler to be used as
a last resort.
:return: An ``IRunTest``.
"""
class IRunTest(Interface):
"""Called from inside ITestCase.run to actually run the test."""
# XXX: jml thinks this ought to be run(case, result), and IRunTestFactory
# shouldn't take a test_case at all.
def run(result):
"""Run the test."""
# TODO:
# - legacy test result interfaces
# - document which test result interfaces are expected above
# - stream result interface
# - make TestControl an interface, use it by composition in
# ExtendedToOriginalDecorator
# - figure out whether .errors, .skip_reasons, .failures, etc. should be
# on IExtendedTestResult or on a separate interface that TestResult also
# implements
# - figure out what to do about failfast and tb_locals
# - interface for TagContext?
# - failureException?
# - loading stuff, e.g. test_suite, load_tests?
# - Matchers, Mismatch?
# - Tests for interface compliance
# - Tests to make sure that users of objects are relying only on their
# interfaces and not the implementation
# - Identify code that's intended to be used by subclassing and try to
# deprecate / limit that usage (or at least make an easily greppable note).
class ITestCaseStrategy(ITestCase):
"""What ``RunTest`` needs to run a test case.
This is a test that has a ``setUp``, a test body, and a ``tearDown``.
Must also be an ``ITestCase`` so the results can be reported.
"""
"""Should local variables be captured in tracebacks?
Can be mutated externally.
"""
__testtools_tb_locals__ = Attribute('__testtools_tb_locals__')
"""List of ``(function, args, kwargs)`` called in reverse order after test.
This list is mutated by ``RunTest``.
"""
_cleanups = Attribute('_cleanups')
"""If non-False, then force the test to fail regardless of behavior.
If not defined, assumed to be False.
"""
force_failure = Attribute('force_failure')
def defaultTestResult():
"""Construct a test result object for reporting results."""
def _get_test_method():
"""Get the test method we are exercising."""
def _run_setup(result):
"""Run the ``setUp`` method of the test."""
def _run_test_method(result):
"""Run the test method.
Must run the method returned by _get_test_method.
"""
def _run_teardown(result):
"""Run the ``tearDown`` method of the test."""
def getDetails():
"""Return a mutable dict mapping names to ``Content``."""
def onException(exc_info, tb_label):
"""Called when we receive an exception.
:param exc_info: A tuple of (exception_type, exception_value,
traceback).
:param tb_label: Used as the label for the traceback, if the traceback
is to be attached as a detail.
"""
class IExtendedTestResult(Interface):
"""Receives test events."""
def addExpectedFailure(test, err=None, details=None):
"""``test`` failed with an expected failure.
For any given test, must be called after ``startTest`` was called for
that test, and before ``stopTest`` has been called for that test.
:param ITestCase test: The test that failed expectedly.
:param exc_info err: An exc_info tuple.
:param dict details: A map of names to ``Content`` objects.
"""
def addError(test, err=None, details=None):
"""``test`` failed with an unexpected error.
For any given test, must be called after ``startTest`` was called for
that test, and before ``stopTest`` has been called for that test.
:param ITestCase test: The test that raised an error.
:param exc_info err: An exc_info tuple.
:param dict details: A map of names to ``Content`` objects.
"""
def addFailure(test, err=None, details=None):
"""``test`` failed as assertion.
For any given test, must be called after ``startTest`` was called for
that test, and before ``stopTest`` has been called for that test.
:param ITestCase test: The test that raised an error.
:param exc_info err: An exc_info tuple.
:param dict details: A map of names to ``Content`` objects.
"""
def addSkip(test, reason=None, details=None):
"""``test`` was skipped, rather than run.
For any given test, must be called after ``startTest`` was called for
that test, and before ``stopTest`` has been called for that test.
:param ITestCase test: The test that raised an error.
:param reason: The reason for the test being skipped.
:param dict details: A map of names to ``Content`` objects.
"""
def addSuccess(test, details=None):
"""``test`` run successfully.
For any given test, must be called after ``startTest`` was called for
that test, and before ``stopTest`` has been called for that test.
:param ITestCase test: The test that raised an error.
:param dict details: A map of names to ``Content`` objects.
"""
def addUnexpectedSuccess(test, details=None):
"""``test`` was expected to fail, but succeeded.
For any given test, must be called after ``startTest`` was called for
that test, and before ``stopTest`` has been called for that test.
:param ITestCase test: The test that raised an error.
:param dict details: A map of names to ``Content`` objects.
"""
def wasSuccessful():
"""Has this result been successful so far?"""
def startTestRun():
"""Started a run of (potentially many) tests."""
def stopTestRun():
"""Finished a run of (potentially many) tests."""
def startTest(test):
"""``test`` started executing.
Must be called after ``startTestRun`` and before ``stopTestRun``.
:param ITestCase test: The test that started.
"""
def stopTest(test):
"""``test`` stopped executing.
Must be called after ``startTestRun`` and before ``stopTestRun``.
:param ITestCase test: The test that stopped.
"""
def tags(new_tags, gone_tags):
"""Change tags for the following tests.
Updates ``current_tags`` such that all tags in ``new_tags`` are in
``current_tags`` and none of ``gone_tags`` are in ``current_tags``.
:param set new_tags: A set of tags that will be applied to any
following tests.
:param set gone_tags: A set of tags that will no longer be applied to
following tests.
"""
def time(timestamp):
"""Tell the test result what the current time is.
:param datetime timestamp: Either a time with timezone information, or
``None`` in which case the test result should get time from the
system.
"""
|