5557.1.7
by John Arbash Meinel
Merge in the bzr.dev 5582 |
1 |
# Copyright (C) 2009, 2010, 2011 Canonical Ltd
|
4711.1.2
by Martin Pool
Start adding tests.per_uifactory |
2 |
#
|
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
#
|
|
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
#
|
|
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
15 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
16 |
||
4711.1.4
by Martin Pool
Change per_uifactory to use subclassing rather than scenarios |
17 |
"""Tests run per UIFactory."""
|
18 |
||
19 |
# Testing UIFactories is a bit interesting because we require they all support a
|
|
20 |
# common interface, but the way they implement it can vary very widely. Between
|
|
21 |
# text, batch-mode, graphical and other potential UIFactories, the requirements
|
|
22 |
# to set up a factory, to make it respond to requests, and to simulate user
|
|
23 |
# input can vary a lot.
|
|
24 |
#
|
|
25 |
# We want tests that therefore allow for the evaluation of the result to vary
|
|
26 |
# per implementation, but we want to check that the supported facilities are
|
|
27 |
# the same across all UIFactorys, unless they're specifically skipped.
|
|
28 |
#
|
|
29 |
# Our normal approach is to use test scenarios but that seems to just end up
|
|
30 |
# creating test-like objects inside the scenario. Therefore we fall back to
|
|
31 |
# the older method of putting the common tests in a mixin.
|
|
32 |
#
|
|
33 |
# Plugins that add new UIFactorys can create their own subclasses.
|
|
4711.1.2
by Martin Pool
Start adding tests.per_uifactory |
34 |
|
35 |
||
36 |
from cStringIO import StringIO |
|
37 |
import unittest |
|
38 |
||
39 |
||
40 |
from bzrlib import ( |
|
41 |
tests, |
|
4906.1.2
by John Arbash Meinel
Get the basic interface tested. |
42 |
transport, |
4711.1.2
by Martin Pool
Start adding tests.per_uifactory |
43 |
ui, |
44 |
)
|
|
45 |
||
46 |
||
4711.1.4
by Martin Pool
Change per_uifactory to use subclassing rather than scenarios |
47 |
class UIFactoryTestMixin(object): |
48 |
"""Common tests for UIFactories.
|
|
49 |
||
50 |
These are supposed to be expressed with no assumptions about how the
|
|
51 |
UIFactory implements the method, only that it does implement them (or
|
|
52 |
fails cleanly), and that the concrete subclass will make arrangements to
|
|
53 |
build a factory and to examine its behaviour.
|
|
54 |
||
55 |
Note that this is *not* a TestCase, because it can't be directly run, but
|
|
56 |
the concrete subclasses should be.
|
|
57 |
"""
|
|
58 |
||
4961.1.2
by Martin Pool
quietness-state is now tracked on UIFactory |
59 |
def test_be_quiet(self): |
60 |
self.factory.be_quiet(True) |
|
61 |
self.assertEquals(True, self.factory.is_quiet()) |
|
62 |
self.factory.be_quiet(False) |
|
63 |
self.assertEquals(False, self.factory.is_quiet()) |
|
64 |
||
5416.1.1
by Martin Pool
Use a structured ui_factory.confirm_action rather than just get_boolean |
65 |
def test_confirm_action(self): |
66 |
# confirm_action should be answered by every ui factory; even
|
|
67 |
# noninteractive ones should have a reasonable default
|
|
68 |
self._load_responses([True]) |
|
5863.6.2
by Jelmer Vernooij
Fix more. |
69 |
result = self.factory.confirm_action(u'Break a lock?', |
70 |
'bzr.lock.break.confirm', |
|
5416.1.1
by Martin Pool
Use a structured ui_factory.confirm_action rather than just get_boolean |
71 |
{})
|
72 |
# will be true either because we read it from the input or because
|
|
73 |
# that's the default
|
|
74 |
self.assertEquals(result, True) |
|
75 |
||
4711.1.4
by Martin Pool
Change per_uifactory to use subclassing rather than scenarios |
76 |
def test_note(self): |
77 |
self.factory.note("a note to the user") |
|
4711.1.7
by Martin Pool
Add UIFactory.show_error, show_warning, show_message |
78 |
self._check_note("a note to the user") |
79 |
||
80 |
def test_show_error(self): |
|
81 |
msg = 'an error occurred' |
|
82 |
self.factory.show_error(msg) |
|
83 |
self._check_show_error(msg) |
|
4711.1.4
by Martin Pool
Change per_uifactory to use subclassing rather than scenarios |
84 |
|
4711.1.8
by Martin Pool
Add show_warning and show_message tests and implementations |
85 |
def test_show_message(self): |
86 |
msg = 'a message' |
|
87 |
self.factory.show_message(msg) |
|
88 |
self._check_show_message(msg) |
|
89 |
||
90 |
def test_show_warning(self): |
|
91 |
msg = 'a warning' |
|
92 |
self.factory.show_warning(msg) |
|
93 |
self._check_show_warning(msg) |
|
94 |
||
4792.8.2
by Martin Pool
New method ui_factory.make_output_stream |
95 |
def test_make_output_stream(self): |
4960.3.1
by Martin Pool
SilentUIFactory now accepts make_output_stream and discards what is written |
96 |
# All UIs must now be able to at least accept output, even if they
|
97 |
# just discard it.
|
|
98 |
output_stream = self.factory.make_output_stream() |
|
4792.8.2
by Martin Pool
New method ui_factory.make_output_stream |
99 |
output_stream.write('hello!') |
100 |
||
4906.1.2
by John Arbash Meinel
Get the basic interface tested. |
101 |
def test_transport_activity(self): |
102 |
# It doesn't matter what the implementation does, we just want to make
|
|
103 |
# sure the interface is there
|
|
104 |
t = transport.get_transport('memory:///') |
|
105 |
self.factory.report_transport_activity(t, 1000, 'write') |
|
106 |
self.factory.report_transport_activity(t, 2000, 'read') |
|
4906.1.4
by John Arbash Meinel
Play around with the ui display a bit more. |
107 |
self.factory.report_transport_activity(t, 4000, None) |
4906.1.2
by John Arbash Meinel
Get the basic interface tested. |
108 |
self.factory.log_transport_activity() |
109 |
self._check_log_transport_activity_noarg() |
|
110 |
self.factory.log_transport_activity(display=True) |
|
111 |
self._check_log_transport_activity_display() |
|
112 |
||
4906.1.7
by John Arbash Meinel
Switch to KiB/K for each value. Don't display if there are no bytes. |
113 |
def test_no_transport_activity(self): |
114 |
# No activity to report
|
|
115 |
t = transport.get_transport('memory:///') |
|
116 |
self.factory.log_transport_activity(display=True) |
|
117 |
self._check_log_transport_activity_display_no_bytes() |
|
118 |
||
4711.1.4
by Martin Pool
Change per_uifactory to use subclassing rather than scenarios |
119 |
|
120 |
class TestTextUIFactory(tests.TestCase, UIFactoryTestMixin): |
|
4711.1.2
by Martin Pool
Start adding tests.per_uifactory |
121 |
|
122 |
def setUp(self): |
|
4711.1.4
by Martin Pool
Change per_uifactory to use subclassing rather than scenarios |
123 |
super(TestTextUIFactory, self).setUp() |
4711.1.2
by Martin Pool
Start adding tests.per_uifactory |
124 |
self.stdin = StringIO() |
125 |
self.stdout = StringIO() |
|
126 |
self.stderr = StringIO() |
|
127 |
self.factory = ui.text.TextUIFactory(self.stdin, self.stdout, |
|
128 |
self.stderr) |
|
129 |
||
4711.1.7
by Martin Pool
Add UIFactory.show_error, show_warning, show_message |
130 |
def _check_note(self, note_text): |
4711.1.4
by Martin Pool
Change per_uifactory to use subclassing rather than scenarios |
131 |
self.assertEquals("%s\n" % note_text, |
132 |
self.stdout.getvalue()) |
|
4711.1.5
by Martin Pool
Add simple tests for CannedInputUIFactory and SilentUIFactory |
133 |
|
4711.1.7
by Martin Pool
Add UIFactory.show_error, show_warning, show_message |
134 |
def _check_show_error(self, msg): |
135 |
self.assertEquals("bzr: error: %s\n" % msg, |
|
136 |
self.stderr.getvalue()) |
|
137 |
self.assertEquals("", self.stdout.getvalue()) |
|
138 |
||
4711.1.8
by Martin Pool
Add show_warning and show_message tests and implementations |
139 |
def _check_show_message(self, msg): |
140 |
self.assertEquals("%s\n" % msg, |
|
141 |
self.stdout.getvalue()) |
|
142 |
self.assertEquals("", self.stderr.getvalue()) |
|
143 |
||
144 |
def _check_show_warning(self, msg): |
|
145 |
self.assertEquals("bzr: warning: %s\n" % msg, |
|
146 |
self.stderr.getvalue()) |
|
147 |
self.assertEquals("", self.stdout.getvalue()) |
|
148 |
||
4906.1.2
by John Arbash Meinel
Get the basic interface tested. |
149 |
def _check_log_transport_activity_noarg(self): |
150 |
self.assertEqual('', self.stdout.getvalue()) |
|
4989.1.4
by Gordon Tyler
Updated tests for changes in output. |
151 |
self.assertContainsRe(self.stderr.getvalue(), r'\d+kB\s+\dkB/s |') |
4906.1.10
by John Arbash Meinel
With the recent changes, transport activity doesn't get debounced. |
152 |
self.assertNotContainsRe(self.stderr.getvalue(), r'Transferred:') |
4906.1.2
by John Arbash Meinel
Get the basic interface tested. |
153 |
|
154 |
def _check_log_transport_activity_display(self): |
|
155 |
self.assertEqual('', self.stdout.getvalue()) |
|
156 |
# Without a TTY, we shouldn't display anything
|
|
157 |
self.assertEqual('', self.stderr.getvalue()) |
|
158 |
||
4906.1.7
by John Arbash Meinel
Switch to KiB/K for each value. Don't display if there are no bytes. |
159 |
def _check_log_transport_activity_display_no_bytes(self): |
160 |
self.assertEqual('', self.stdout.getvalue()) |
|
161 |
# Without a TTY, we shouldn't display anything
|
|
162 |
self.assertEqual('', self.stderr.getvalue()) |
|
163 |
||
5416.1.1
by Martin Pool
Use a structured ui_factory.confirm_action rather than just get_boolean |
164 |
def _load_responses(self, responses): |
165 |
self.factory.stdin.seek(0) |
|
166 |
self.factory.stdin.writelines([(r and "y\n" or "n\n") for r in responses]) |
|
167 |
self.factory.stdin.seek(0) |
|
168 |
||
4906.1.2
by John Arbash Meinel
Get the basic interface tested. |
169 |
|
170 |
class TestTTYTextUIFactory(TestTextUIFactory): |
|
171 |
||
172 |
def setUp(self): |
|
173 |
super(TestTTYTextUIFactory, self).setUp() |
|
174 |
||
175 |
class TTYStringIO(object): |
|
176 |
"""Thunk over to StringIO() for everything but 'isatty'"""
|
|
177 |
||
178 |
def __init__(self): |
|
179 |
self.__dict__['_sio'] = StringIO() |
|
180 |
||
181 |
def isatty(self): |
|
182 |
return True |
|
183 |
||
184 |
def __getattr__(self, name): |
|
185 |
return getattr(self._sio, name) |
|
186 |
||
187 |
def __setattr__(self, name, value): |
|
188 |
return setattr(self._sio, name, value) |
|
4989.1.6
by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used. |
189 |
|
4906.1.2
by John Arbash Meinel
Get the basic interface tested. |
190 |
# Remove 'TERM' == 'dumb' which causes us to *not* treat output as a
|
191 |
# real terminal, even though isatty returns True
|
|
5570.3.6
by Vincent Ladeuil
Get rid of all _captureVar() calls, no test failures, pfew. |
192 |
self.overrideEnv('TERM', None) |
4906.1.2
by John Arbash Meinel
Get the basic interface tested. |
193 |
self.stderr = TTYStringIO() |
194 |
self.stdout = TTYStringIO() |
|
195 |
self.factory = ui.text.TextUIFactory(self.stdin, self.stdout, |
|
196 |
self.stderr) |
|
197 |
||
198 |
def _check_log_transport_activity_display(self): |
|
199 |
self.assertEqual('', self.stdout.getvalue()) |
|
4989.1.6
by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used. |
200 |
# Displaying the result should write to the progress stream using
|
201 |
# base-10 units (see HACKING.txt).
|
|
4906.1.5
by John Arbash Meinel
Include the KiB/s for the transfer. |
202 |
self.assertContainsRe(self.stderr.getvalue(), |
4989.1.4
by Gordon Tyler
Updated tests for changes in output. |
203 |
r'Transferred: 7kB' |
204 |
r' \(\d+\.\dkB/s r:2kB w:1kB u:4kB\)') |
|
4906.1.7
by John Arbash Meinel
Switch to KiB/K for each value. Don't display if there are no bytes. |
205 |
|
206 |
def _check_log_transport_activity_display_no_bytes(self): |
|
207 |
self.assertEqual('', self.stdout.getvalue()) |
|
208 |
# Without actual bytes transferred, we should report nothing
|
|
209 |
self.assertEqual('', self.stderr.getvalue()) |
|
4906.1.2
by John Arbash Meinel
Get the basic interface tested. |
210 |
|
4711.1.5
by Martin Pool
Add simple tests for CannedInputUIFactory and SilentUIFactory |
211 |
|
212 |
class TestSilentUIFactory(tests.TestCase, UIFactoryTestMixin): |
|
213 |
# discards output, therefore tests for output expect nothing
|
|
214 |
||
215 |
def setUp(self): |
|
216 |
super(TestSilentUIFactory, self).setUp() |
|
217 |
self.factory = ui.SilentUIFactory() |
|
218 |
||
4711.1.7
by Martin Pool
Add UIFactory.show_error, show_warning, show_message |
219 |
def _check_note(self, note_text): |
4711.1.5
by Martin Pool
Add simple tests for CannedInputUIFactory and SilentUIFactory |
220 |
# it's just discarded
|
221 |
pass
|
|
222 |
||
4711.1.7
by Martin Pool
Add UIFactory.show_error, show_warning, show_message |
223 |
def _check_show_error(self, msg): |
224 |
pass
|
|
225 |
||
4711.1.8
by Martin Pool
Add show_warning and show_message tests and implementations |
226 |
def _check_show_message(self, msg): |
227 |
pass
|
|
228 |
||
229 |
def _check_show_warning(self, msg): |
|
230 |
pass
|
|
231 |
||
4906.1.2
by John Arbash Meinel
Get the basic interface tested. |
232 |
def _check_log_transport_activity_noarg(self): |
233 |
pass
|
|
234 |
||
235 |
def _check_log_transport_activity_display(self): |
|
236 |
pass
|
|
237 |
||
4906.1.7
by John Arbash Meinel
Switch to KiB/K for each value. Don't display if there are no bytes. |
238 |
def _check_log_transport_activity_display_no_bytes(self): |
239 |
pass
|
|
240 |
||
5416.1.1
by Martin Pool
Use a structured ui_factory.confirm_action rather than just get_boolean |
241 |
def _load_responses(self, responses): |
242 |
pass
|
|
243 |
||
4711.1.5
by Martin Pool
Add simple tests for CannedInputUIFactory and SilentUIFactory |
244 |
|
245 |
class TestCannedInputUIFactory(tests.TestCase, UIFactoryTestMixin): |
|
246 |
# discards output, reads input from variables
|
|
247 |
||
248 |
def setUp(self): |
|
249 |
super(TestCannedInputUIFactory, self).setUp() |
|
250 |
self.factory = ui.CannedInputUIFactory([]) |
|
251 |
||
4711.1.7
by Martin Pool
Add UIFactory.show_error, show_warning, show_message |
252 |
def _check_note(self, note_text): |
253 |
pass
|
|
254 |
||
255 |
def _check_show_error(self, msg): |
|
256 |
pass
|
|
257 |
||
4711.1.8
by Martin Pool
Add show_warning and show_message tests and implementations |
258 |
def _check_show_message(self, msg): |
259 |
pass
|
|
260 |
||
261 |
def _check_show_warning(self, msg): |
|
262 |
pass
|
|
263 |
||
4906.1.2
by John Arbash Meinel
Get the basic interface tested. |
264 |
def _check_log_transport_activity_noarg(self): |
265 |
pass
|
|
4711.1.7
by Martin Pool
Add UIFactory.show_error, show_warning, show_message |
266 |
|
4906.1.2
by John Arbash Meinel
Get the basic interface tested. |
267 |
def _check_log_transport_activity_display(self): |
268 |
pass
|
|
4906.1.7
by John Arbash Meinel
Switch to KiB/K for each value. Don't display if there are no bytes. |
269 |
|
270 |
def _check_log_transport_activity_display_no_bytes(self): |
|
271 |
pass
|
|
5416.1.1
by Martin Pool
Use a structured ui_factory.confirm_action rather than just get_boolean |
272 |
|
273 |
def _load_responses(self, responses): |
|
274 |
self.factory.responses.extend(responses) |