1# Copyright (c) 2009-2010 testtools developers. See LICENSE for details.
2
3"""Doubles of test result objects, useful for testing unittest code."""
4
5__all__ = [
6    'Python26TestResult',
7    'Python27TestResult',
8    'ExtendedTestResult',
9    'StreamResult',
10    ]
11
12
13from testtools.tags import TagContext
14
15
16class LoggingBase(object):
17    """Basic support for logging of results."""
18
19    def __init__(self):
20        self._events = []
21        self.shouldStop = False
22        self._was_successful = True
23        self.testsRun = 0
24
25
26class Python26TestResult(LoggingBase):
27    """A precisely python 2.6 like test result, that logs."""
28
29    def addError(self, test, err):
30        self._was_successful = False
31        self._events.append(('addError', test, err))
32
33    def addFailure(self, test, err):
34        self._was_successful = False
35        self._events.append(('addFailure', test, err))
36
37    def addSuccess(self, test):
38        self._events.append(('addSuccess', test))
39
40    def startTest(self, test):
41        self._events.append(('startTest', test))
42        self.testsRun += 1
43
44    def stop(self):
45        self.shouldStop = True
46
47    def stopTest(self, test):
48        self._events.append(('stopTest', test))
49
50    def wasSuccessful(self):
51        return self._was_successful
52
53
54class Python27TestResult(Python26TestResult):
55    """A precisely python 2.7 like test result, that logs."""
56
57    def __init__(self):
58        super(Python27TestResult, self).__init__()
59        self.failfast = False
60
61    def addError(self, test, err):
62        super(Python27TestResult, self).addError(test, err)
63        if self.failfast:
64            self.stop()
65
66    def addFailure(self, test, err):
67        super(Python27TestResult, self).addFailure(test, err)
68        if self.failfast:
69            self.stop()
70
71    def addExpectedFailure(self, test, err):
72        self._events.append(('addExpectedFailure', test, err))
73
74    def addSkip(self, test, reason):
75        self._events.append(('addSkip', test, reason))
76
77    def addUnexpectedSuccess(self, test):
78        self._events.append(('addUnexpectedSuccess', test))
79        if self.failfast:
80            self.stop()
81
82    def startTestRun(self):
83        self._events.append(('startTestRun',))
84
85    def stopTestRun(self):
86        self._events.append(('stopTestRun',))
87
88
89class ExtendedTestResult(Python27TestResult):
90    """A test result like the proposed extended unittest result API."""
91
92    def __init__(self):
93        super(ExtendedTestResult, self).__init__()
94        self._tags = TagContext()
95
96    def addError(self, test, err=None, details=None):
97        self._was_successful = False
98        self._events.append(('addError', test, err or details))
99
100    def addFailure(self, test, err=None, details=None):
101        self._was_successful = False
102        self._events.append(('addFailure', test, err or details))
103
104    def addExpectedFailure(self, test, err=None, details=None):
105        self._events.append(('addExpectedFailure', test, err or details))
106
107    def addSkip(self, test, reason=None, details=None):
108        self._events.append(('addSkip', test, reason or details))
109
110    def addSuccess(self, test, details=None):
111        if details:
112            self._events.append(('addSuccess', test, details))
113        else:
114            self._events.append(('addSuccess', test))
115
116    def addUnexpectedSuccess(self, test, details=None):
117        self._was_successful = False
118        if details is not None:
119            self._events.append(('addUnexpectedSuccess', test, details))
120        else:
121            self._events.append(('addUnexpectedSuccess', test))
122
123    def progress(self, offset, whence):
124        self._events.append(('progress', offset, whence))
125
126    def startTestRun(self):
127        super(ExtendedTestResult, self).startTestRun()
128        self._was_successful = True
129        self._tags = TagContext()
130
131    def startTest(self, test):
132        super(ExtendedTestResult, self).startTest(test)
133        self._tags = TagContext(self._tags)
134
135    def stopTest(self, test):
136        self._tags = self._tags.parent
137        super(ExtendedTestResult, self).stopTest(test)
138
139    @property
140    def current_tags(self):
141        return self._tags.get_current_tags()
142
143    def tags(self, new_tags, gone_tags):
144        self._tags.change_tags(new_tags, gone_tags)
145        self._events.append(('tags', new_tags, gone_tags))
146
147    def time(self, time):
148        self._events.append(('time', time))
149
150    def wasSuccessful(self):
151        return self._was_successful
152
153
154class StreamResult(object):
155    """A StreamResult implementation for testing.
156
157    All events are logged to _events.
158    """
159
160    def __init__(self):
161        self._events = []
162
163    def startTestRun(self):
164        self._events.append(('startTestRun',))
165
166    def stopTestRun(self):
167        self._events.append(('stopTestRun',))
168
169    def status(self, test_id=None, test_status=None, test_tags=None,
170        runnable=True, file_name=None, file_bytes=None, eof=False,
171        mime_type=None, route_code=None, timestamp=None):
172        self._events.append(('status', test_id, test_status, test_tags,
173            runnable, file_name, file_bytes, eof, mime_type, route_code,
174            timestamp))
175