Merge lp:~frankban/juju-quickstart/support-old-series into lp:juju-quickstart
- support-old-series
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 117 |
Proposed branch: | lp:~frankban/juju-quickstart/support-old-series |
Merge into: | lp:juju-quickstart |
Diff against target: |
446 lines (+265/-35) 10 files modified
HACKING.rst (+41/-0) Makefile (+10/-0) quickstart/juju.py (+2/-2) quickstart/manage.py (+0/-1) quickstart/platform_support.py (+1/-4) quickstart/tests/functional/__init__.py (+41/-0) quickstart/tests/functional/test_functional.py (+139/-0) quickstart/tests/test_juju.py (+30/-22) setup.cfg (+0/-1) tox.ini (+1/-5) |
To merge this branch: | bzr merge lp:~frankban/juju-quickstart/support-old-series |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju GUI Hackers | Pending | ||
Review via email:
|
Commit message
Description of the change
Enable tests for trusty and utopic.
Fix the unit test suite so that tests pass
when run in trusty and utopic scenarios.
Also add some simple functional tests. In those
tests, Quickstart is run against a real Juju env.
See the changes in the HACKING file for instructions
about running functional tests.
To QA this, run `make check` and `make fcheck`: the
latter can take some time.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Francesco Banconi (frankban) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Brad Crittenden (bac) wrote : | # |
LGTM. No QA.
https:/
File quickstart/
https:/
quickstart/
cls.output, cls.error = run_quickstart(
Thanks for the thoughtful test implementation.
It may be worth noting that run_quickstart only happens once per suite
not once per test as it isn't super obvious since we don't use
setUpClass all that much.
- 138. By Francesco Banconi
-
Changes as per review.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Francesco Banconi (frankban) wrote : | # |
Please take a look.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
LGTM Thanks for getting this working! I'll QA once we chat about my
comment.
https:/
File quickstart/
https:/
quickstart/
envs.get_
As a precautionary measure I would prefer if there was a default
environment name for these tests. That way there would be no possible
way someone would accidentally run these tests on a live environment.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
QA OK Thanks for this branch!
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Francesco Banconi (frankban) wrote : | # |
*** Submitted:
Enable tests for trusty and utopic.
Fix the unit test suite so that tests pass
when run in trusty and utopic scenarios.
Also add some simple functional tests. In those
tests, Quickstart is run against a real Juju env.
See the changes in the HACKING file for instructions
about running functional tests.
To QA this, run `make check` and `make fcheck`: the
latter can take some time.
R=bac, jeff.pihach
CC=
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Francesco Banconi (frankban) wrote : | # |
Thanks for the reviews!
Preview Diff
1 | === modified file 'HACKING.rst' | |||
2 | --- HACKING.rst 2015-01-30 09:28:38 +0000 | |||
3 | +++ HACKING.rst 2015-02-03 14:13:23 +0000 | |||
4 | @@ -67,6 +67,43 @@ | |||
5 | 67 | 67 | ||
6 | 68 | Run ``make help`` for more information about all the available make targets. | 68 | Run ``make help`` for more information about all the available make targets. |
7 | 69 | 69 | ||
8 | 70 | Running functional tests | ||
9 | 71 | ~~~~~~~~~~~~~~~~~~~~~~~~ | ||
10 | 72 | |||
11 | 73 | The Juju Quickstart test suite includes functional tests exercising the | ||
12 | 74 | application execution against a real Juju environment. Functional tests are | ||
13 | 75 | not run by default (i.e. when using ``make test`` or ``make check``), but they | ||
14 | 76 | can be activated by setting the ``JUJU_QUICKSTART_FTESTS`` environment variable | ||
15 | 77 | to ``1``, or, in a simpler way, by running ``make ftest`` or ``make fcheck``. | ||
16 | 78 | |||
17 | 79 | Note that functional tests are not intended to be run in the day-by-day | ||
18 | 80 | development process. Their goal is to automate part of the release QA. | ||
19 | 81 | |||
20 | 82 | Functional tests require: | ||
21 | 83 | |||
22 | 84 | - some time to complete their execution: a real Juju environment is | ||
23 | 85 | bootstrapped in the process; | ||
24 | 86 | - a Juju home correctly set up with at least one environment defined in the | ||
25 | 87 | ``environments.yaml`` file; | ||
26 | 88 | - SSH keys already generated for the user running the tests; | ||
27 | 89 | - a working Internet connection. | ||
28 | 90 | |||
29 | 91 | By default, the current default environment is used to run those tests. | ||
30 | 92 | To change the environment, use the JUJU_ENV environment variable, e.g.:: | ||
31 | 93 | |||
32 | 94 | make fcheck JUJU_ENV=myenv | ||
33 | 95 | |||
34 | 96 | The environment used by the functional suite is destroyed after the tests | ||
35 | 97 | complete. For this reason, **ensure the selected environment is not in use**. | ||
36 | 98 | |||
37 | 99 | To run the test using a customized build of Juju, pass the ``JUJU`` environment | ||
38 | 100 | variable to ``make``, e.g.:: | ||
39 | 101 | |||
40 | 102 | make fcheck JUJU=$GOPATH/bin/juju | ||
41 | 103 | |||
42 | 104 | Also note that when running functional tests against a local environment, the | ||
43 | 105 | password for sudo privileges may be asked while the suite is run. | ||
44 | 106 | |||
45 | 70 | Requirements | 107 | Requirements |
46 | 71 | ~~~~~~~~~~~~ | 108 | ~~~~~~~~~~~~ |
47 | 72 | 109 | ||
48 | @@ -157,6 +194,10 @@ | |||
49 | 157 | Pre-release QA | 194 | Pre-release QA |
50 | 158 | ~~~~~~~~~~~~~~ | 195 | ~~~~~~~~~~~~~~ |
51 | 159 | 196 | ||
52 | 197 | Run the Quickstart functional tests on all supported platforms:: | ||
53 | 198 | |||
54 | 199 | make fcheck | ||
55 | 200 | |||
56 | 160 | The general steps for manual QA (until we get a continuous integration set up | 201 | The general steps for manual QA (until we get a continuous integration set up |
57 | 161 | with functional tests) should be run on trusty, utopic and vivid. | 202 | with functional tests) should be run on trusty, utopic and vivid. |
58 | 162 | 203 | ||
59 | 163 | 204 | ||
60 | === modified file 'Makefile' | |||
61 | --- Makefile 2015-01-30 16:34:50 +0000 | |||
62 | +++ Makefile 2015-02-03 14:13:23 +0000 | |||
63 | @@ -66,6 +66,14 @@ | |||
64 | 66 | # Remove the virtualenv used in previous configurations. | 66 | # Remove the virtualenv used in previous configurations. |
65 | 67 | rm -rfv .venv/ | 67 | rm -rfv .venv/ |
66 | 68 | 68 | ||
67 | 69 | .PHONY: fcheck | ||
68 | 70 | fcheck: setup | ||
69 | 71 | $(MAKE) check JUJU_QUICKSTART_FTESTS=1 | ||
70 | 72 | |||
71 | 73 | .PHONY: ftest | ||
72 | 74 | ftest: setup | ||
73 | 75 | $(MAKE) test JUJU_QUICKSTART_FTESTS=1 | ||
74 | 76 | |||
75 | 69 | .PHONY: help | 77 | .PHONY: help |
76 | 70 | help: | 78 | help: |
77 | 71 | @echo -e 'Juju Quickstart - list of make targets:\n' | 79 | @echo -e 'Juju Quickstart - list of make targets:\n' |
78 | @@ -73,6 +81,8 @@ | |||
79 | 73 | @echo 'make test - Run tests.' | 81 | @echo 'make test - Run tests.' |
80 | 74 | @echo 'make lint - Run linter and pep8.' | 82 | @echo 'make lint - Run linter and pep8.' |
81 | 75 | @echo 'make check - Run all the tests and lint in all supported scenarios.' | 83 | @echo 'make check - Run all the tests and lint in all supported scenarios.' |
82 | 84 | @echo 'make ftest - Run tests (including functional tests).' | ||
83 | 85 | @echo 'make fcheck - Run functional tests and lint in all scenarios.' | ||
84 | 76 | @echo 'make source - Create source package.' | 86 | @echo 'make source - Create source package.' |
85 | 77 | @echo 'make install - Install on local system.' | 87 | @echo 'make install - Install on local system.' |
86 | 78 | @echo 'make clean - Get rid of bytecode files, build and dist dirs, venvs.' | 88 | @echo 'make clean - Get rid of bytecode files, build and dist dirs, venvs.' |
87 | 79 | 89 | ||
88 | === modified file 'quickstart/juju.py' | |||
89 | --- quickstart/juju.py 2014-12-16 11:10:10 +0000 | |||
90 | +++ quickstart/juju.py 2015-02-03 14:13:23 +0000 | |||
91 | @@ -148,7 +148,7 @@ | |||
92 | 148 | Overridden to add logging in the case the payload is text. | 148 | Overridden to add logging in the case the payload is text. |
93 | 149 | """ | 149 | """ |
94 | 150 | if opcode == OPCODE_TEXT: | 150 | if opcode == OPCODE_TEXT: |
96 | 151 | message = payload.decode('utf-8') | 151 | message = payload.decode('utf-8', 'ignore') |
97 | 152 | logging.debug('API message: --> {}'.format(message)) | 152 | logging.debug('API message: --> {}'.format(message)) |
98 | 153 | return super(WebSocketConnection, self).send(payload, opcode=opcode) | 153 | return super(WebSocketConnection, self).send(payload, opcode=opcode) |
99 | 154 | 154 | ||
100 | @@ -159,6 +159,6 @@ | |||
101 | 159 | """ | 159 | """ |
102 | 160 | data = super(WebSocketConnection, self).recv() | 160 | data = super(WebSocketConnection, self).recv() |
103 | 161 | if isinstance(data, bytes): | 161 | if isinstance(data, bytes): |
105 | 162 | message = data.decode('utf-8') | 162 | message = data.decode('utf-8', 'ignore') |
106 | 163 | logging.debug('API message: <-- {}'.format(message)) | 163 | logging.debug('API message: <-- {}'.format(message)) |
107 | 164 | return data | 164 | return data |
108 | 165 | 165 | ||
109 | === modified file 'quickstart/manage.py' | |||
110 | --- quickstart/manage.py 2015-01-12 12:10:38 +0000 | |||
111 | +++ quickstart/manage.py 2015-02-03 14:13:23 +0000 | |||
112 | @@ -386,7 +386,6 @@ | |||
113 | 386 | 386 | ||
114 | 387 | Exit with an error if the provided arguments are not valid. | 387 | Exit with an error if the provided arguments are not valid. |
115 | 388 | """ | 388 | """ |
116 | 389 | |||
117 | 390 | # Determine the host platform. This needs to be done early as it affects | 389 | # Determine the host platform. This needs to be done early as it affects |
118 | 391 | # the options we present. | 390 | # the options we present. |
119 | 392 | platform = platform_support.get_platform() | 391 | platform = platform_support.get_platform() |
120 | 393 | 392 | ||
121 | === modified file 'quickstart/platform_support.py' | |||
122 | --- quickstart/platform_support.py 2014-08-25 16:57:41 +0000 | |||
123 | +++ quickstart/platform_support.py 2015-02-03 14:13:23 +0000 | |||
124 | @@ -55,10 +55,7 @@ | |||
125 | 55 | 55 | ||
126 | 56 | 56 | ||
127 | 57 | def get_platform(): | 57 | def get_platform(): |
132 | 58 | """Return the platform of the host. | 58 | """Return the platform of the host.""" |
129 | 59 | |||
130 | 60 | Raises UnsupportedOS if a platform we don't support is detected. | ||
131 | 61 | """ | ||
133 | 62 | system = platform.system() | 59 | system = platform.system() |
134 | 63 | if system == 'Darwin': | 60 | if system == 'Darwin': |
135 | 64 | return settings.OSX | 61 | return settings.OSX |
136 | 65 | 62 | ||
137 | === added directory 'quickstart/tests/functional' | |||
138 | === added file 'quickstart/tests/functional/__init__.py' | |||
139 | --- quickstart/tests/functional/__init__.py 1970-01-01 00:00:00 +0000 | |||
140 | +++ quickstart/tests/functional/__init__.py 2015-02-03 14:13:23 +0000 | |||
141 | @@ -0,0 +1,41 @@ | |||
142 | 1 | # This file is part of the Juju Quickstart Plugin, which lets users set up a | ||
143 | 2 | # Juju environment in very few steps (https://launchpad.net/juju-quickstart). | ||
144 | 3 | # Copyright (C) 2015 Canonical Ltd. | ||
145 | 4 | # | ||
146 | 5 | # This program is free software: you can redistribute it and/or modify it under | ||
147 | 6 | # the terms of the GNU Affero General Public License version 3, as published by | ||
148 | 7 | # the Free Software Foundation. | ||
149 | 8 | # | ||
150 | 9 | # This program is distributed in the hope that it will be useful, but WITHOUT | ||
151 | 10 | # ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
152 | 11 | # SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
153 | 12 | # Affero General Public License for more details. | ||
154 | 13 | # | ||
155 | 14 | # You should have received a copy of the GNU Affero General Public License | ||
156 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
157 | 16 | |||
158 | 17 | """Juju Quickstart functional tests package. | ||
159 | 18 | |||
160 | 19 | This package includes functional tests for Juju Quickstart. | ||
161 | 20 | In those tests, Juju Quickstart is run to bootstrap and deploy the Juju GUI | ||
162 | 21 | in a real Juju environment. For this reason, completing the suite takes a | ||
163 | 22 | while. Therefore tests are disabled by default, and are intended to be only run | ||
164 | 23 | before releasing a new version of the application. | ||
165 | 24 | |||
166 | 25 | To run the tests, set the JUJU_QUICKSTART_FTESTS environment variable to "1", | ||
167 | 26 | or use "make ftest/fcheck". | ||
168 | 27 | |||
169 | 28 | Functional tests require: | ||
170 | 29 | - a Juju home correctly set up with at least one environment defined in the | ||
171 | 30 | environments.yaml file; | ||
172 | 31 | - SSH keys already generated for the user running the tests; | ||
173 | 32 | - a working Internet connection. | ||
174 | 33 | |||
175 | 34 | By default, the current default environment is used to run the application. | ||
176 | 35 | To change the environment, set the JUJU_ENV environment variable, e.g.: | ||
177 | 36 | |||
178 | 37 | make fcheck JUJU_ENV=myenv | ||
179 | 38 | |||
180 | 39 | Also note that when running functional tests against a local environment, the | ||
181 | 40 | password for sudo privileges may be asked while the suite is run. | ||
182 | 41 | """ | ||
183 | 0 | 42 | ||
184 | === added file 'quickstart/tests/functional/test_functional.py' | |||
185 | --- quickstart/tests/functional/test_functional.py 1970-01-01 00:00:00 +0000 | |||
186 | +++ quickstart/tests/functional/test_functional.py 2015-02-03 14:13:23 +0000 | |||
187 | @@ -0,0 +1,139 @@ | |||
188 | 1 | # This file is part of the Juju Quickstart Plugin, which lets users set up a | ||
189 | 2 | # Juju environment in very few steps (https://launchpad.net/juju-quickstart). | ||
190 | 3 | # Copyright (C) 2015 Canonical Ltd. | ||
191 | 4 | # | ||
192 | 5 | # This program is free software: you can redistribute it and/or modify it under | ||
193 | 6 | # the terms of the GNU Affero General Public License version 3, as published by | ||
194 | 7 | # the Free Software Foundation. | ||
195 | 8 | # | ||
196 | 9 | # This program is distributed in the hope that it will be useful, but WITHOUT | ||
197 | 10 | # ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
198 | 11 | # SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
199 | 12 | # Affero General Public License for more details. | ||
200 | 13 | # | ||
201 | 14 | # You should have received a copy of the GNU Affero General Public License | ||
202 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
203 | 16 | |||
204 | 17 | """Functional tests for Juju Quickstart.""" | ||
205 | 18 | |||
206 | 19 | from __future__ import unicode_literals | ||
207 | 20 | |||
208 | 21 | import functools | ||
209 | 22 | import json | ||
210 | 23 | import os | ||
211 | 24 | import unittest | ||
212 | 25 | |||
213 | 26 | import quickstart | ||
214 | 27 | from quickstart import ( | ||
215 | 28 | platform_support, | ||
216 | 29 | settings, | ||
217 | 30 | utils, | ||
218 | 31 | ) | ||
219 | 32 | from quickstart.models import envs | ||
220 | 33 | |||
221 | 34 | |||
222 | 35 | # Define the name of the environment variable used to run the functional tests. | ||
223 | 36 | FTEST_ENV_VAR = 'JUJU_QUICKSTART_FTESTS' | ||
224 | 37 | |||
225 | 38 | |||
226 | 39 | def skip_if_disbled(func): | ||
227 | 40 | """Decorate a test method so that it is only run when required/possible.""" | ||
228 | 41 | # Check that functional tests are enabled. | ||
229 | 42 | if os.getenv(FTEST_ENV_VAR) != '1': | ||
230 | 43 | return unittest.skip( | ||
231 | 44 | 'to run functional tests, set {} to "1"'.format(FTEST_ENV_VAR)) | ||
232 | 45 | # Check that a Juju environment can be found. | ||
233 | 46 | env_name = envs.get_default_env_name() | ||
234 | 47 | if env_name is None: | ||
235 | 48 | return unittest.skip('cannot find a configured Juju environment') | ||
236 | 49 | |||
237 | 50 | @functools.wraps(func) | ||
238 | 51 | def decorated(cls_or_self): | ||
239 | 52 | # Decorate the function to update the received class or instance with | ||
240 | 53 | # the Juju env name. | ||
241 | 54 | cls_or_self.env_name = env_name | ||
242 | 55 | return func(cls_or_self) | ||
243 | 56 | |||
244 | 57 | return decorated | ||
245 | 58 | |||
246 | 59 | |||
247 | 60 | def run_juju(*args): | ||
248 | 61 | """Run the juju command with the given args. | ||
249 | 62 | |||
250 | 63 | Return a tuple including the command exit code, its output and error. | ||
251 | 64 | """ | ||
252 | 65 | platform = platform_support.get_platform() | ||
253 | 66 | cmd, _ = platform_support.get_juju_command(platform) | ||
254 | 67 | return utils.call(cmd, *args) | ||
255 | 68 | |||
256 | 69 | |||
257 | 70 | def run_quickstart(env_name, *args): | ||
258 | 71 | """Run the Juju Quickstart command. | ||
259 | 72 | |||
260 | 73 | Return a tuple including the command exit code, its output and error. | ||
261 | 74 | """ | ||
262 | 75 | package_dir = os.path.dirname(quickstart.__file__) | ||
263 | 76 | cmd = os.path.abspath(os.path.join(package_dir, '..', 'juju-quickstart')) | ||
264 | 77 | return utils.call( | ||
265 | 78 | cmd, '-e', env_name, '--distro-only', '--no-browser', *args) | ||
266 | 79 | |||
267 | 80 | |||
268 | 81 | class TestFunctional(unittest.TestCase): | ||
269 | 82 | |||
270 | 83 | @classmethod | ||
271 | 84 | @skip_if_disbled | ||
272 | 85 | def setUpClass(cls): | ||
273 | 86 | # Run Juju Quickstart to bootstrap Juju and deploy the Juju GUI. | ||
274 | 87 | # Note that this is done once per suite. The resulting environment is | ||
275 | 88 | # then destroyed when the suite completes. | ||
276 | 89 | cls.retcode, cls.output, cls.error = run_quickstart(cls.env_name) | ||
277 | 90 | |||
278 | 91 | @classmethod | ||
279 | 92 | @skip_if_disbled | ||
280 | 93 | def tearDownClass(cls): | ||
281 | 94 | # Destroy the environment. | ||
282 | 95 | run_juju('destroy-environment', cls.env_name, '-y', '--force') | ||
283 | 96 | |||
284 | 97 | def test_executed(self): | ||
285 | 98 | # The application successfully completed its execution. | ||
286 | 99 | self.assertEqual(0, self.retcode) | ||
287 | 100 | self.assertIn('done!', self.output) | ||
288 | 101 | self.assertEqual('', self.error) | ||
289 | 102 | |||
290 | 103 | def test_gui_started(self): | ||
291 | 104 | # At the end of the process, the Juju GUI unit is started. | ||
292 | 105 | retcode, output, _ = run_juju( | ||
293 | 106 | 'status', '-e', self.env_name, '--format', 'json') | ||
294 | 107 | self.assertEqual(0, retcode) | ||
295 | 108 | status = json.loads(output) | ||
296 | 109 | # The Juju GUI service is exposed. | ||
297 | 110 | service = status['services'][settings.JUJU_GUI_SERVICE_NAME] | ||
298 | 111 | self.assertTrue(service['exposed']) | ||
299 | 112 | # The Juju GUI unit is started. | ||
300 | 113 | unit = service['units']['{}/0'.format(settings.JUJU_GUI_SERVICE_NAME)] | ||
301 | 114 | self.assertEqual('started', unit['agent-state']) | ||
302 | 115 | |||
303 | 116 | def test_idempotent(self): | ||
304 | 117 | # The application can be run again on an already bootstrapped | ||
305 | 118 | # environment. | ||
306 | 119 | retcode, output, error = run_quickstart(self.env_name) | ||
307 | 120 | self.assertEqual(0, retcode) | ||
308 | 121 | msg = 'reusing the already bootstrapped {} environment' | ||
309 | 122 | self.assertIn(msg.format(self.env_name), output) | ||
310 | 123 | self.assertEqual('', error) | ||
311 | 124 | |||
312 | 125 | def test_version(self): | ||
313 | 126 | # The application correctly prints out its own version. | ||
314 | 127 | retcode, output, error = run_quickstart(self.env_name, '--version') | ||
315 | 128 | self.assertEqual(0, retcode) | ||
316 | 129 | self.assertEqual('', output) | ||
317 | 130 | self.assertEqual( | ||
318 | 131 | 'juju-quickstart {}\n'.format(quickstart.get_version()), error) | ||
319 | 132 | |||
320 | 133 | def test_bundle_deployment(self): | ||
321 | 134 | # The application can be used to deploy bundles. | ||
322 | 135 | retcode, output, error = run_quickstart( | ||
323 | 136 | self.env_name, 'bundle:mediawiki/single') | ||
324 | 137 | self.assertEqual(0, retcode) | ||
325 | 138 | self.assertIn('bundle deployment request accepted', output) | ||
326 | 139 | self.assertEqual('', error) | ||
327 | 0 | 140 | ||
328 | === modified file 'quickstart/tests/test_juju.py' | |||
329 | --- quickstart/tests/test_juju.py 2014-12-16 15:53:25 +0000 | |||
330 | +++ quickstart/tests/test_juju.py 2015-02-03 14:13:23 +0000 | |||
331 | @@ -63,8 +63,13 @@ | |||
332 | 63 | api_url = self.api_url | 63 | api_url = self.api_url |
333 | 64 | with mock.patch('websocket.create_connection') as mock_connect: | 64 | with mock.patch('websocket.create_connection') as mock_connect: |
334 | 65 | self.env = juju.Environment(api_url) | 65 | self.env = juju.Environment(api_url) |
337 | 66 | mock_connect.assert_called_once_with( | 66 | # In old versions of jujuclient the SSL options are not passed as |
338 | 67 | api_url, origin=api_url, sslopt=juju.SSLOPT) | 67 | # kwargs to create_connection. |
339 | 68 | if len(mock_connect.call_args[1]) == 1: | ||
340 | 69 | mock_connect.assert_called_once_with(api_url, origin=api_url) | ||
341 | 70 | else: | ||
342 | 71 | mock_connect.assert_called_once_with( | ||
343 | 72 | api_url, origin=api_url, sslopt=juju.SSLOPT) | ||
344 | 68 | # Keep track of watcher changes in the changesets list. | 73 | # Keep track of watcher changes in the changesets list. |
345 | 69 | self.changesets = [] | 74 | self.changesets = [] |
346 | 70 | 75 | ||
347 | @@ -345,49 +350,52 @@ | |||
348 | 345 | 350 | ||
349 | 346 | def setUp(self): | 351 | def setUp(self): |
350 | 347 | self.conn = juju.WebSocketConnection() | 352 | self.conn = juju.WebSocketConnection() |
351 | 348 | # The send method calls the send_frame one. | ||
352 | 349 | self.conn.send_frame = self.mock_send = mock.Mock() | ||
353 | 350 | # The recv method calls the recv_data one. | ||
354 | 351 | self.conn.recv_data = self.mock_recv = mock.Mock() | ||
355 | 352 | 353 | ||
356 | 353 | def test_send(self): | 354 | def test_send(self): |
357 | 354 | # Outgoing messages are properly logged. | 355 | # Outgoing messages are properly logged. |
358 | 355 | with helpers.assert_logs(['API message: --> my message'], 'debug'): | 356 | with helpers.assert_logs(['API message: --> my message'], 'debug'): |
361 | 356 | self.conn.send('my message') | 357 | with mock.patch('websocket.WebSocket.send') as mock_send: |
362 | 357 | self.assertTrue(self.mock_send.called) | 358 | self.conn.send('my message') |
363 | 359 | mock_send.assert_called_once_with( | ||
364 | 360 | 'my message', opcode=juju.OPCODE_TEXT) | ||
365 | 358 | 361 | ||
366 | 359 | def test_send_unicode(self): | 362 | def test_send_unicode(self): |
367 | 360 | # Outgoing unicode messages are properly logged. | 363 | # Outgoing unicode messages are properly logged. |
368 | 361 | expected = 'API message: --> {}'.format(self.snowman) | 364 | expected = 'API message: --> {}'.format(self.snowman) |
369 | 362 | with helpers.assert_logs([expected], 'debug'): | 365 | with helpers.assert_logs([expected], 'debug'): |
372 | 363 | self.conn.send(self.snowman.encode('utf-8')) | 366 | with mock.patch('websocket.WebSocket.send') as mock_send: |
373 | 364 | self.assertTrue(self.mock_send.called) | 367 | self.conn.send(self.snowman.encode('utf-8')) |
374 | 368 | mock_send.assert_called_once_with( | ||
375 | 369 | self.snowman.encode('utf-8'), opcode=juju.OPCODE_TEXT) | ||
376 | 365 | 370 | ||
377 | 366 | def test_send_not_text(self): | 371 | def test_send_not_text(self): |
378 | 367 | # Outgoing non-textual messages are not logged. | 372 | # Outgoing non-textual messages are not logged. |
379 | 368 | with helpers.assert_logs([], 'debug'): | 373 | with helpers.assert_logs([], 'debug'): |
382 | 369 | self.conn.send(0x0, opcode=websocket.ABNF.OPCODE_BINARY) | 374 | with mock.patch('websocket.WebSocket.send') as mock_send: |
383 | 370 | self.assertTrue(self.mock_send.called) | 375 | self.conn.send(0x0, opcode=websocket.ABNF.OPCODE_BINARY) |
384 | 376 | mock_send.assert_called_once_with( | ||
385 | 377 | 0x0, opcode=websocket.ABNF.OPCODE_BINARY) | ||
386 | 371 | 378 | ||
387 | 372 | def test_recv(self): | 379 | def test_recv(self): |
388 | 373 | # Incoming messages are properly logged. | 380 | # Incoming messages are properly logged. |
389 | 374 | self.mock_recv.return_value = (juju.OPCODE_TEXT, b'my message') | ||
390 | 375 | with helpers.assert_logs(['API message: <-- my message'], 'debug'): | 381 | with helpers.assert_logs(['API message: <-- my message'], 'debug'): |
393 | 376 | self.conn.recv() | 382 | with mock.patch('websocket.WebSocket.recv') as mock_recv: |
394 | 377 | self.mock_recv.assert_called_once_with() | 383 | mock_recv.return_value = (b'my message') |
395 | 384 | message = self.conn.recv() | ||
396 | 385 | self.assertEqual('my message', message) | ||
397 | 378 | 386 | ||
398 | 379 | def test_recv_unicode(self): | 387 | def test_recv_unicode(self): |
399 | 380 | # Incoming unicode messages are properly logged. | 388 | # Incoming unicode messages are properly logged. |
400 | 381 | self.mock_recv.return_value = ( | ||
401 | 382 | juju.OPCODE_TEXT, self.snowman.encode('utf-8')) | ||
402 | 383 | expected = 'API message: <-- {}'.format(self.snowman) | 389 | expected = 'API message: <-- {}'.format(self.snowman) |
403 | 384 | with helpers.assert_logs([expected], 'debug'): | 390 | with helpers.assert_logs([expected], 'debug'): |
406 | 385 | self.conn.recv() | 391 | with mock.patch('websocket.WebSocket.recv') as mock_recv: |
407 | 386 | self.mock_recv.assert_called_once_with() | 392 | mock_recv.return_value = self.snowman.encode('utf-8') |
408 | 393 | message = self.conn.recv() | ||
409 | 394 | self.assertEqual(self.snowman.encode('utf-8'), message) | ||
410 | 387 | 395 | ||
411 | 388 | def test_recv_not_text(self): | 396 | def test_recv_not_text(self): |
412 | 389 | # Incoming non-textual messages are not logged. | 397 | # Incoming non-textual messages are not logged. |
413 | 390 | self.mock_recv.return_value = (websocket.ABNF.OPCODE_BINARY, 0x0) | ||
414 | 391 | with helpers.assert_logs([], 'debug'): | 398 | with helpers.assert_logs([], 'debug'): |
417 | 392 | self.conn.recv() | 399 | with mock.patch('websocket.WebSocket.recv') as mock_recv: |
418 | 393 | self.mock_recv.assert_called_once_with() | 400 | mock_recv.return_value = 0x0 |
419 | 401 | self.conn.recv() | ||
420 | 394 | 402 | ||
421 | === modified file 'setup.cfg' | |||
422 | --- setup.cfg 2015-01-16 12:32:38 +0000 | |||
423 | +++ setup.cfg 2015-02-03 14:13:23 +0000 | |||
424 | @@ -15,6 +15,5 @@ | |||
425 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
426 | 16 | 16 | ||
427 | 17 | [nosetests] | 17 | [nosetests] |
428 | 18 | detailed-errors=1 | ||
429 | 19 | nocapture=1 | 18 | nocapture=1 |
430 | 20 | verbosity=2 | 19 | verbosity=2 |
431 | 21 | 20 | ||
432 | === modified file 'tox.ini' | |||
433 | --- tox.ini 2015-01-30 09:28:38 +0000 | |||
434 | +++ tox.ini 2015-02-03 14:13:23 +0000 | |||
435 | @@ -18,11 +18,7 @@ | |||
436 | 18 | # The envlist option must only include platform scenarios. In essence, those | 18 | # The envlist option must only include platform scenarios. In essence, those |
437 | 19 | # are used to test Juju Quickstart with the specific dependencies present in | 19 | # are used to test Juju Quickstart with the specific dependencies present in |
438 | 20 | # each supported OS platform. | 20 | # each supported OS platform. |
444 | 21 | envlist = pypi,ppa,vivid | 21 | envlist = pypi,ppa,trusty,utopic,vivid |
440 | 22 | # XXX frankban: currently tests do not pass on trusty and utopic scenarios. | ||
441 | 23 | # Fix the tests, then remove the line above and uncomment the line below. | ||
442 | 24 | # envlist = pypi,ppa,trusty,utopic,vivid | ||
443 | 25 | |||
445 | 26 | 22 | ||
446 | 27 | # Define the base requirements and commands to use when testing the program. | 23 | # Define the base requirements and commands to use when testing the program. |
447 | 28 | 24 |
Reviewers: mp+248150_ code.launchpad. net,
Message:
Please take a look.
Description:
Enable tests for trusty and utopic.
Fix the unit test suite so that tests pass
when run in trusty and utopic scenarios.
Also add some simple functional tests. In those
tests, Quickstart is run against a real Juju env.
See the changes in the HACKING file for instructions
about running functional tests.
To QA this, run `make check` and `make fcheck`: the
latter can take some time.
https:/ /code.launchpad .net/~frankban/ juju-quickstart /support- old-series/ +merge/ 248150
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/197240043/
Affected files (+265, -35 lines): manage. py platform_ support. py tests/functiona l/__init_ _.py tests/functiona l/test_ functional. py tests/test_ juju.py
M HACKING.rst
M Makefile
A [revision details]
M quickstart/juju.py
M quickstart/
M quickstart/
A quickstart/
A quickstart/
M quickstart/
M setup.cfg
M tox.ini