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
|
# Copyright (c) 2008-2016 testtools developers. See LICENSE for details.
"""Helpers for tests."""
__all__ = [
'LoggingResult',
]
import sys
from testtools import TestResult
from testtools.content import StackLinesContent
from testtools.matchers import (
AfterPreprocessing,
Equals,
MatchesDict,
MatchesListwise,
)
from testtools import runtest
# GZ 2010-08-12: Don't do this, pointlessly creates an exc_info cycle
try:
raise Exception
except Exception:
an_exc_info = sys.exc_info()
# Deprecated: This classes attributes are somewhat non deterministic which
# leads to hard to predict tests (because Python upstream are changing things.
class LoggingResult(TestResult):
"""TestResult that logs its event to a list."""
def __init__(self, log):
self._events = log
super().__init__()
def startTest(self, test):
self._events.append(('startTest', test))
super().startTest(test)
def stop(self):
self._events.append('stop')
super().stop()
def stopTest(self, test):
self._events.append(('stopTest', test))
super().stopTest(test)
def addFailure(self, test, error):
self._events.append(('addFailure', test, error))
super().addFailure(test, error)
def addError(self, test, error):
self._events.append(('addError', test, error))
super().addError(test, error)
def addSkip(self, test, reason):
self._events.append(('addSkip', test, reason))
super().addSkip(test, reason)
def addSuccess(self, test):
self._events.append(('addSuccess', test))
super().addSuccess(test)
def startTestRun(self):
self._events.append('startTestRun')
super().startTestRun()
def stopTestRun(self):
self._events.append('stopTestRun')
super().stopTestRun()
def done(self):
self._events.append('done')
super().done()
def tags(self, new_tags, gone_tags):
self._events.append(('tags', new_tags, gone_tags))
super().tags(new_tags, gone_tags)
def time(self, a_datetime):
self._events.append(('time', a_datetime))
super().time(a_datetime)
def is_stack_hidden():
return StackLinesContent.HIDE_INTERNAL_STACK
def hide_testtools_stack(should_hide=True):
result = StackLinesContent.HIDE_INTERNAL_STACK
StackLinesContent.HIDE_INTERNAL_STACK = should_hide
return result
def run_with_stack_hidden(should_hide, f, *args, **kwargs):
old_should_hide = hide_testtools_stack(should_hide)
try:
return f(*args, **kwargs)
finally:
hide_testtools_stack(old_should_hide)
class FullStackRunTest(runtest.RunTest):
def _run_user(self, fn, *args, **kwargs):
return run_with_stack_hidden(
False,
super()._run_user, fn, *args, **kwargs)
class MatchesEvents:
"""Match a list of test result events.
Specify events as a data structure. Ordinary Python objects within this
structure will be compared exactly, but you can also use matchers at any
point.
"""
def __init__(self, *expected):
self._expected = expected
def _make_matcher(self, obj):
# This isn't very safe for general use, but is good enough to make
# some tests in this module more readable.
if hasattr(obj, 'match'):
return obj
elif isinstance(obj, tuple) or isinstance(obj, list):
return MatchesListwise(
[self._make_matcher(item) for item in obj])
elif isinstance(obj, dict):
return MatchesDict({
key: self._make_matcher(value)
for key, value in obj.items()})
else:
return Equals(obj)
def match(self, observed):
matcher = self._make_matcher(self._expected)
return matcher.match(observed)
class AsText(AfterPreprocessing):
"""Match the text of a Content instance."""
def __init__(self, matcher, annotate=True):
super().__init__(
lambda log: log.as_text(), matcher, annotate=annotate)
def raise_(exception):
"""Raise ``exception``.
Useful for raising exceptions when it is inconvenient to use a statement
(e.g. in a lambda).
:param Exception exception: An exception to raise.
:raises: Whatever exception is
"""
raise exception
|