Merge lp:~canonical-platform-qa/snappy-ecosystem-tests/adding-test-runner into lp:snappy-ecosystem-tests
- adding-test-runner
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | I Ahmad |
Approved revision: | 18 |
Merged at revision: | 14 |
Proposed branch: | lp:~canonical-platform-qa/snappy-ecosystem-tests/adding-test-runner |
Merge into: | lp:snappy-ecosystem-tests |
Diff against target: |
1367 lines (+856/-144) 29 files modified
README.rst (+76/-24) mk-venv (+44/-0) pylint.cfg (+4/-4) requirements.txt (+13/-2) run_checks (+1/-1) run_system_tests (+25/-0) setup.py (+48/-0) snappy_ecosystem_tests/commons/__init__.py (+19/-0) snappy_ecosystem_tests/commons/config.py (+173/-0) snappy_ecosystem_tests/configs/__init__.py (+19/-0) snappy_ecosystem_tests/configs/ecosystem_tests.cfg (+20/-0) snappy_ecosystem_tests/configs/pytest.cfg (+2/-0) snappy_ecosystem_tests/data/__init__.py (+0/-19) snappy_ecosystem_tests/helpers/fixture_setup.py (+95/-0) snappy_ecosystem_tests/helpers/test_base.py (+32/-0) snappy_ecosystem_tests/helpers/ubuntu_store_tests_base.py (+0/-19) snappy_ecosystem_tests/helpers/web_test_base.py (+35/-17) snappy_ecosystem_tests/run.py (+47/-0) snappy_ecosystem_tests/snapcraft/__init__.py (+19/-0) snappy_ecosystem_tests/snapcraft/snapcraft.py (+8/-26) snappy_ecosystem_tests/snapd/__init__.py (+19/-0) snappy_ecosystem_tests/tests/__init__.py (+0/-19) snappy_ecosystem_tests/tests/data/entity/entity.json (+6/-0) snappy_ecosystem_tests/tests/test_store_login.py (+5/-3) snappy_ecosystem_tests/unittests/test_snapcraft.py (+3/-1) snappy_ecosystem_tests/utils/json.py (+30/-0) snappy_ecosystem_tests/utils/singleton.py (+38/-0) snappy_ecosystem_tests/utils/storeconfig.py (+29/-9) snappy_ecosystem_tests/utils/test_data.py (+46/-0) |
To merge this branch: | bzr merge lp:~canonical-platform-qa/snappy-ecosystem-tests/adding-test-runner |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
I Ahmad (community) | Approve | ||
platform-qa-bot | continuous-integration | Approve | |
Review via email: mp+317132@code.launchpad.net |
Commit message
This change includes:
* Adding pytest as a test runner.
* Adding config files
* Adding mechanism to read test data.
* Making pylint more strict: fail when a warning message is returned.
Description of the change
This change includes:
* Adding pytest as a test runner since nose2 has issues when testtools report failures
* Adding config files to store urls, store environment values, etc. And the mechanism to read them.
* Adding mechanism to read test data for users (Can be extended for any entity).
* Making pylint more strict: fail when a warning message is returned.
Can be included in a next iteration:
* Improve selenium config values and page objects.
* read snappy-ecosystem related arguments from commandline.
platform-qa-bot (platform-qa-bot) wrote : | # |
- 15. By Heber Parrucci
-
fixing pylint issues
platform-qa-bot (platform-qa-bot) wrote : | # |
PASSED: Continuous integration, rev:15
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 16. By Heber Parrucci
-
removing print statement
platform-qa-bot (platform-qa-bot) wrote : | # |
PASSED: Continuous integration, rev:16
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 17. By Heber Parrucci
-
passing filtered arguments to main without modifying the args command line
platform-qa-bot (platform-qa-bot) wrote : | # |
PASSED: Continuous integration, rev:17
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
I Ahmad (iahmad) wrote : | # |
I would suggest to not check in the credentials to the public bzr branch as bots can pick it up, this should be concealed using the environment variables or if we can find a way to encrypt them at check in time and decrypt it when these were needed for the setup (like travis)
- 18. By Heber Parrucci
-
Addressing review feedback regarding credentials:
Now it is read from a user config file that is outside the repo in the host machine. If that config is not found, then it reads the credentials from env variables.
The idea is to store the config with the credentials in a private repository, and then Jenkins will get it and store in the host machine when running the tests.
The same mechanism is used in ubuntu-system- tests.
Heber Parrucci (heber013) wrote : | # |
> I would suggest to not check in the credentials to the public bzr branch as
> bots can pick it up, this should be concealed using the environment variables
> or if we can find a way to encrypt them at check in time and decrypt it when
> these were needed for the setup (like travis)
Thanks for review!
Now credentials are read from a user config file that is outside the repo in the host machine. If that config is not found, then it reads the credentials from env variables.
The idea is to store the config with the credentials in a private repository, and then Jenkins will get it and store in the host machine when running the tests.
The same mechanism is used in ubuntu-
platform-qa-bot (platform-qa-bot) wrote : | # |
PASSED: Continuous integration, rev:18
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === renamed file 'README' => 'README.rst' |
2 | --- README 2017-02-08 14:27:31 +0000 |
3 | +++ README.rst 2017-02-15 19:16:15 +0000 |
4 | @@ -1,29 +1,81 @@ |
5 | -How to setup and execute snappy ecosystem tests |
6 | -=============================================== |
7 | -Please make sure you have following dependencies installed |
8 | -1. Python version >= 3.5 |
9 | -2. nosetests >= 1.3.7 |
10 | -3. xmlrunner >= 1.7.7 |
11 | -4. geckodriver webdriver for Firefox >= 0.13.0 |
12 | -5. chromedriver webdriver for Chrome >= 2.27 |
13 | - |
14 | -Make sure webdrivers are added to $PATH |
15 | - |
16 | - |
17 | -To run the tests checkout the branch follow the below steps |
18 | -=========================================================== |
19 | +Snappy Ecosystem Tests |
20 | +###################### |
21 | + |
22 | +Automated system tests for snappy ecosystem: snapcraft, store and snapd. |
23 | + |
24 | + |
25 | +To run the tests checkout the branch and follow the below steps |
26 | +=============================================================== |
27 | $ bzr branch lp:snappy-ecosystem-tests |
28 | $ cd snappy-ecosystem-tests/ |
29 | -$ export UBUNTU_STORE_LOGIN_EMAIL=<store account email> |
30 | -$ export UBUNTU_STORE_LOGIN_PASSWORD=<store account password> |
31 | -$ export STAGING=<1 or 0>, To test against staging or production server respectively |
32 | -$ nosetests --with-xunit |
33 | - |
34 | - |
35 | -Running code analysis with pylint |
36 | -================================= |
37 | +$ ./run_system_tests snappy_ecosystem_tests |
38 | + |
39 | +It will create a virtual env with all the dependencies defined in requirements.txt and run all the tests |
40 | +A pytest runner is used: http://docs.pytest.org/en/latest/ |
41 | + |
42 | +To run all tests in a python package: |
43 | +$ ./run_system_tests snappy_ecosystem_tests/tests/example_package |
44 | + |
45 | +To run all test in a python module: |
46 | +$ ./run_system_tests snappy_ecosystem_tests/tests/example_package/example_module.py |
47 | + |
48 | +To run all tests in a python class: |
49 | +$ ./run_system_tests snappy_ecosystem_tests/tests/example_package/example_module.py::ExampleClass |
50 | + |
51 | +To run a particular test in a python class: |
52 | +$ ./run_system_tests snappy_ecosystem_tests/tests/example_package/example_module.py::ExampleClass::example_test |
53 | + |
54 | +To run a tests that match with a expression: |
55 | +./run_system_tests -k stringexpr |
56 | +# only run tests with names that match the |
57 | +# "string expression", e.g. "MyClass and not method" |
58 | +# will select TestMyClass.test_something |
59 | +# but not TestMyClass.test_method_simple |
60 | + |
61 | +You can also specify the arguments as python packages separated by dots: |
62 | +$ ./run_system_tests --pyargs tests.example_package.example_module |
63 | +Notice that in this case you skip the root dir snappy_ecosystem_tests and for python modules skip the .py |
64 | + |
65 | +To see all options refer to: http://doc.pytest.org/en/latest/usage.html#specifying-tests-selecting-tests |
66 | + |
67 | +Tests Results |
68 | +============= |
69 | +By default the tests results will be stored in 'snappy-ecosystem-results.xml' |
70 | + |
71 | +Parameters |
72 | +========== |
73 | +If you are behind a proxy you can specify --proxy option |
74 | +All pytest parameters are allowed |
75 | + |
76 | +Config files |
77 | +============ |
78 | +You can find configurations files in 'config' folder: |
79 | + |
80 | +ecosystem_tests.cfg stores the snappy ecosystem related config like: APIs urls, Web urls, store to use, etc. |
81 | +You can change this config file location by setting the env variable: XDG_CONFIG_HOME |
82 | + |
83 | +pytest.cfg stores the config related to pytest |
84 | + |
85 | +Changing store: |
86 | +=============== |
87 | +You can change the store to use in config file ecosystem_tests.cfg |
88 | +or by setting the env variable TEST_STORE with values: 'staging' or 'production'. |
89 | +It will first try to read the config file, then the env variable and finally |
90 | +if none of them are provided it will take 'staging' as default. |
91 | + |
92 | + |
93 | +Running static code analysis and/or unittest |
94 | +============================================ |
95 | To run static code analysis you can execute from root directory: |
96 | -$ ./run_pylint |
97 | +$ ./run_checks --static |
98 | It will store the results in pylint-results.txt |
99 | -The config file with all the rules is pylint.cfg |
100 | +The config file with pylint rules is pylint.cfg |
101 | + |
102 | +If you want to run unittests: |
103 | +$ ./run_checks --unit |
104 | + |
105 | +If you want to run both: |
106 | +$ ./run_checks --all |
107 | + |
108 | +If you are behind a proxy you can specify --proxy option |
109 | |
110 | |
111 | === added file 'mk-venv' |
112 | --- mk-venv 1970-01-01 00:00:00 +0000 |
113 | +++ mk-venv 2017-02-15 19:16:15 +0000 |
114 | @@ -0,0 +1,44 @@ |
115 | +#!/bin/bash |
116 | + |
117 | +# |
118 | +# Snappy Ecosystem Tests |
119 | +# Copyright (C) 2017 Canonical |
120 | +# |
121 | +# This program is free software: you can redistribute it and/or modify |
122 | +# it under the terms of the GNU General Public License as published by |
123 | +# the Free Software Foundation, either version 3 of the License, or |
124 | +# (at your option) any later version. |
125 | +# |
126 | +# This program is distributed in the hope that it will be useful, |
127 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
128 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
129 | +# GNU General Public License for more details. |
130 | +# |
131 | +# You should have received a copy of the GNU General Public License |
132 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
133 | +# |
134 | + |
135 | +virtualenv --python=python3 ve |
136 | +. ve/bin/activate |
137 | + |
138 | + |
139 | +while [[ $# -gt 1 ]] |
140 | +do |
141 | + |
142 | +key="$1" |
143 | + |
144 | +case $key in |
145 | + --proxy) |
146 | + proxy="$2" |
147 | + shift # past argument |
148 | + ;; |
149 | +esac |
150 | +shift # past argument or value |
151 | +done |
152 | + |
153 | +if [ "$proxy" ]; then |
154 | + echo "Using proxy: $proxy to install dependencies" |
155 | + pip install --proxy $proxy -r requirements.txt |
156 | +else |
157 | + pip install -r requirements.txt |
158 | +fi |
159 | |
160 | === modified file 'pylint.cfg' |
161 | --- pylint.cfg 2017-02-10 18:18:45 +0000 |
162 | +++ pylint.cfg 2017-02-15 19:16:15 +0000 |
163 | @@ -99,7 +99,7 @@ |
164 | [VARIABLES] |
165 | |
166 | # Tells whether we should check for unused import in __init__ files. |
167 | -init-import=no |
168 | +init-import=yes |
169 | |
170 | # A regular expression matching the name of dummy variables (i.e. expectedly |
171 | # not used). |
172 | @@ -222,7 +222,7 @@ |
173 | [FORMAT] |
174 | |
175 | # Maximum number of characters on a single line. |
176 | -max-line-length=100 |
177 | +max-line-length=80 |
178 | |
179 | # Regexp for a line that is allowed to be longer than the limit. |
180 | ignore-long-lines=^\s*(# )?<?https?://\S+>?$ |
181 | @@ -286,7 +286,7 @@ |
182 | [MISCELLANEOUS] |
183 | |
184 | # List of note tags to take in consideration, separated by a comma. |
185 | -notes=FIXME,XXX,TODO |
186 | +notes= |
187 | |
188 | |
189 | [TYPECHECK] |
190 | @@ -361,7 +361,7 @@ |
191 | max-attributes=7 |
192 | |
193 | # Minimum number of public methods for a class (see R0903). |
194 | -min-public-methods=2 |
195 | +min-public-methods=1 |
196 | |
197 | # Maximum number of public methods for a class (see R0904). |
198 | max-public-methods=20 |
199 | |
200 | === modified file 'requirements.txt' |
201 | --- requirements.txt 2017-02-10 18:18:45 +0000 |
202 | +++ requirements.txt 2017-02-15 19:16:15 +0000 |
203 | @@ -1,3 +1,14 @@ |
204 | +pytest |
205 | +testtools |
206 | +unittest2 |
207 | +testscenarios |
208 | +fixtures |
209 | +selenium |
210 | +configparser==3.5.0 |
211 | +progressbar33==2.4 |
212 | +requests==2.9.1 |
213 | +simplejson==3.8.2 |
214 | +pyxdg==0.25 |
215 | +jsonschema==2.5.1 |
216 | pexpect |
217 | -selenium |
218 | -unittest2 |
219 | +chromedriver_installer |
220 | |
221 | === modified file 'run_checks' |
222 | --- run_checks 2017-02-10 19:30:21 +0000 |
223 | +++ run_checks 2017-02-15 19:16:15 +0000 |
224 | @@ -35,7 +35,7 @@ |
225 | ve_pylint/bin/python3 -m pylint snappy_ecosystem_tests --reports=n --rcfile=pylint.cfg > pylint-results.txt |
226 | |
227 | result=$? |
228 | - if [ $result != 0 ] && [ $result != 4 ]; then |
229 | + if [ $result != 0 ]; then |
230 | echo -e -n "${RED}Pylint errors. Check pylint output for more information\n" |
231 | exit 1; |
232 | else |
233 | |
234 | === added file 'run_system_tests' |
235 | --- run_system_tests 1970-01-01 00:00:00 +0000 |
236 | +++ run_system_tests 2017-02-15 19:16:15 +0000 |
237 | @@ -0,0 +1,25 @@ |
238 | +#!/bin/bash |
239 | + |
240 | +# |
241 | +# Snappy Ecosystem Tests |
242 | +# Copyright (C) 2017 Canonical |
243 | +# |
244 | +# This program is free software: you can redistribute it and/or modify |
245 | +# it under the terms of the GNU General Public License as published by |
246 | +# the Free Software Foundation, either version 3 of the License, or |
247 | +# (at your option) any later version. |
248 | +# |
249 | +# This program is distributed in the hope that it will be useful, |
250 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
251 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
252 | +# GNU General Public License for more details. |
253 | +# |
254 | +# You should have received a copy of the GNU General Public License |
255 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
256 | +# |
257 | + |
258 | +. ./mk-venv "$@" |
259 | + |
260 | +ve/bin/python3 ./snappy_ecosystem_tests/run.py "$@" -c snappy_ecosystem_tests/configs/pytest.cfg --ignore snappy_ecosystem_tests/unittests/ --junitxml snappy-ecosystem-results.xml |
261 | + |
262 | +deactivate |
263 | |
264 | === added file 'setup.py' |
265 | --- setup.py 1970-01-01 00:00:00 +0000 |
266 | +++ setup.py 2017-02-15 19:16:15 +0000 |
267 | @@ -0,0 +1,48 @@ |
268 | +#!/usr/bin/env python3 |
269 | + |
270 | +# |
271 | +# Snappy Ecosystem Tests |
272 | +# Copyright (C) 2017 Canonical |
273 | +# |
274 | +# This program is free software: you can redistribute it and/or modify |
275 | +# it under the terms of the GNU General Public License as published by |
276 | +# the Free Software Foundation, either version 3 of the License, or |
277 | +# (at your option) any later version. |
278 | +# |
279 | +# This program is distributed in the hope that it will be useful, |
280 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
281 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
282 | +# GNU General Public License for more details. |
283 | +# |
284 | +# You should have received a copy of the GNU General Public License |
285 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
286 | +# |
287 | + |
288 | +import sys |
289 | +from setuptools import find_packages, setup |
290 | + |
291 | +assert sys.version_info >= (3,), 'Python 3 is required' |
292 | + |
293 | + |
294 | +VERSION = '1.0' |
295 | + |
296 | + |
297 | +setup( |
298 | + name='snappy-ecosystem-tests', |
299 | + version=VERSION, |
300 | + description='Automated tests for Snappy Ecosystem.', |
301 | + author='Canonical Platform QA Team', |
302 | + author_email='qa-team@lists.canonical.com', |
303 | + url='https://launchpad.net/~snappy-ecosystem-tests-dev', |
304 | + license='GPLv3', |
305 | + packages=find_packages(), |
306 | + package_data={ |
307 | + 'snappy_ecosystem_tests': ['tests/data/*/*'] |
308 | + }, |
309 | + entry_points={ |
310 | + 'console_scripts': [ |
311 | + 'snappy_ecosystem_tests = snappy_ecosystem_tests.run:main' |
312 | + ] |
313 | + }, |
314 | + test_suite='snappy_ecosystem_tests.unittests' |
315 | +) |
316 | |
317 | === added directory 'snappy_ecosystem_tests/commons' |
318 | === added file 'snappy_ecosystem_tests/commons/__init__.py' |
319 | --- snappy_ecosystem_tests/commons/__init__.py 1970-01-01 00:00:00 +0000 |
320 | +++ snappy_ecosystem_tests/commons/__init__.py 2017-02-15 19:16:15 +0000 |
321 | @@ -0,0 +1,19 @@ |
322 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
323 | + |
324 | +# |
325 | +# Snappy Ecosystem Tests |
326 | +# Copyright (C) 2017 Canonical |
327 | +# |
328 | +# This program is free software: you can redistribute it and/or modify |
329 | +# it under the terms of the GNU General Public License as published by |
330 | +# the Free Software Foundation, either version 3 of the License, or |
331 | +# (at your option) any later version. |
332 | +# |
333 | +# This program is distributed in the hope that it will be useful, |
334 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
335 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
336 | +# GNU General Public License for more details. |
337 | +# |
338 | +# You should have received a copy of the GNU General Public License |
339 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
340 | +# |
341 | |
342 | === added file 'snappy_ecosystem_tests/commons/config.py' |
343 | --- snappy_ecosystem_tests/commons/config.py 1970-01-01 00:00:00 +0000 |
344 | +++ snappy_ecosystem_tests/commons/config.py 2017-02-15 19:16:15 +0000 |
345 | @@ -0,0 +1,173 @@ |
346 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
347 | + |
348 | +# |
349 | +# Snappy Ecosystem Tests |
350 | +# Copyright (C) 2017 Canonical |
351 | +# |
352 | +# This program is free software: you can redistribute it and/or modify |
353 | +# it under the terms of the GNU General Public License as published by |
354 | +# the Free Software Foundation, either version 3 of the License, or |
355 | +# (at your option) any later version. |
356 | +# |
357 | +# This program is distributed in the hope that it will be useful, |
358 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
359 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
360 | +# GNU General Public License for more details. |
361 | +# |
362 | +# You should have received a copy of the GNU General Public License |
363 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
364 | +# |
365 | + |
366 | +"""Manage tests config files: get existing one, create new one and store it""" |
367 | + |
368 | +import configparser |
369 | +import logging |
370 | +import os |
371 | + |
372 | +LOGGER = logging.getLogger(__name__) |
373 | + |
374 | +DEFAULT_CONF = 'ecosystem_tests.cfg' |
375 | +KEY_DEFAULT = 'default' |
376 | + |
377 | + |
378 | +def get_config_dir(): |
379 | + """Return the path to the tests configuration directory.""" |
380 | + conf_dir = os.environ.get( |
381 | + 'XDG_CONFIG_HOME', os.path.realpath(__file__ + '/../../configs')) |
382 | + return conf_dir |
383 | + |
384 | + |
385 | +def get_user_config_dir(): |
386 | + """Return the path to the user configuration directory.""" |
387 | + conf_dir = os.environ.get( |
388 | + 'XDG_USER_CONFIG_HOME', os.path.expanduser('~/.config')) |
389 | + return conf_dir |
390 | + |
391 | + |
392 | +def get_config_section(): |
393 | + """Return the name of config section to use.""" |
394 | + return os.environ.get('CONFIG_SECTION', KEY_DEFAULT) |
395 | + |
396 | + |
397 | +def _get_config_stack_from_file(file_path): |
398 | + """Return config stack from specified file path.""" |
399 | + ecosystem_config = SnappyEcosystemTestsConfig(file_path) |
400 | + ecosystem_config.read_config_from_file() |
401 | + return ecosystem_config |
402 | + |
403 | + |
404 | +class ConfigStack: |
405 | + """Class that represents different config stacks""" |
406 | + |
407 | + def __init__(self, dir_path=None, file_name=None): |
408 | + self.__config = self.__create_config_stack(dir_path, file_name) |
409 | + |
410 | + @property |
411 | + def config(self): |
412 | + """Return the current config""" |
413 | + return self.__get_config() |
414 | + |
415 | + def set_config(self, dir_path=None, file_name=None): |
416 | + """Set the current config for the given dirpath and file name. |
417 | + :param dir_path: the dir in which the config file is located. |
418 | + If None it takes the default one returned by get_config_dir() |
419 | + :param file_name: the config file name. |
420 | + If None it takes the default one stored in DEFAULT_CONF |
421 | + :return the created config as a dict |
422 | + """ |
423 | + self.__config = self.__create_config_stack(dir_path, file_name) |
424 | + |
425 | + def release_config(self): |
426 | + """Release the current config for those cases that |
427 | + explicitly want to modify it""" |
428 | + self.__config = None |
429 | + |
430 | + def __get_config(self): |
431 | + """Get current config. Set it in the case is None""" |
432 | + if self.__config is None: |
433 | + self.set_config() |
434 | + return self.__config |
435 | + |
436 | + @staticmethod |
437 | + def __create_config_stack(dir_path=None, file_name=None): |
438 | + """Create the config stack for the given dirpath and file name |
439 | + :param dir_path: the dir in which the config file is located. |
440 | + If None it takes the default one returned by get_config_dir() |
441 | + :param file_name: the config file name. |
442 | + If None it takes the default one stored in DEFAULT_CONF |
443 | + :return the created config as a dict |
444 | + """ |
445 | + full_path = os.path.join(dir_path or get_config_dir(), |
446 | + file_name or DEFAULT_CONF) |
447 | + return _get_config_stack_from_file(full_path) |
448 | + |
449 | + |
450 | +class SnappyEcosystemTestsConfig: |
451 | + |
452 | + """Class to get and save test configuration data.""" |
453 | + |
454 | + def __init__(self, file_name=None): |
455 | + """ |
456 | + Construct the config and parser object. |
457 | + :param file_name: Name of config file to load. Default file is used if |
458 | + value is not specified. |
459 | + """ |
460 | + user_config_dir = get_config_dir() |
461 | + if not os.path.exists(user_config_dir): |
462 | + os.mkdir(user_config_dir) |
463 | + self.file_path = os.path.join( |
464 | + user_config_dir, file_name or DEFAULT_CONF) |
465 | + self.config = configparser.ConfigParser( |
466 | + allow_no_value=True, empty_lines_in_values=False) |
467 | + |
468 | + def set(self, section, option_name, value): |
469 | + """Set a config value for the given section. |
470 | + :param section: the section of the config in which update |
471 | + the given value |
472 | + :param option_name: Name of config option. |
473 | + :param value: Value to set. |
474 | + """ |
475 | + self.config[section][option_name] = value |
476 | + self.save() |
477 | + |
478 | + def get(self, section, option_name, default=''): |
479 | + """Get a config value for a given section. |
480 | + If section and/or value are not found, return default if |
481 | + provided or raise exception |
482 | + :param section: the section of the config in which search |
483 | + for the given value. |
484 | + :param option_name: Name of config option to get. |
485 | + :param default: Value to return as default if section and/or |
486 | + item don't exist. |
487 | + :return: Config option value if it exists. In case that section |
488 | + and/or item don't exists, |
489 | + then return default value if provided, or raise exception""" |
490 | + try: |
491 | + return self.config.get(section, option_name) |
492 | + except(configparser.NoSectionError, configparser.NoOptionError): |
493 | + if default: |
494 | + return default |
495 | + else: |
496 | + raise |
497 | + |
498 | + def get_section(self, section): |
499 | + """ |
500 | + Return a particular section of config |
501 | + :param section: the section name to retrieve |
502 | + :return: a Section object |
503 | + """ |
504 | + return self.config[section] |
505 | + |
506 | + def save(self): |
507 | + """Save the config to file path""" |
508 | + mode = 'r+' if os.path.exists(self.file_path) else 'w' |
509 | + with open(self.file_path, mode) as _f: |
510 | + self.config.write(_f) |
511 | + |
512 | + def read_config_from_file(self): |
513 | + """Read config from file""" |
514 | + self.config.read(self.file_path) |
515 | + |
516 | + |
517 | +CONFIG_STACK = ConfigStack().config |
518 | +USER_CONFIG_STACK = ConfigStack(dir_path=get_user_config_dir()).config |
519 | |
520 | === added directory 'snappy_ecosystem_tests/configs' |
521 | === added file 'snappy_ecosystem_tests/configs/__init__.py' |
522 | --- snappy_ecosystem_tests/configs/__init__.py 1970-01-01 00:00:00 +0000 |
523 | +++ snappy_ecosystem_tests/configs/__init__.py 2017-02-15 19:16:15 +0000 |
524 | @@ -0,0 +1,19 @@ |
525 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
526 | + |
527 | +# |
528 | +# Snappy Ecosystem Tests |
529 | +# Copyright (C) 2017 Canonical |
530 | +# |
531 | +# This program is free software: you can redistribute it and/or modify |
532 | +# it under the terms of the GNU General Public License as published by |
533 | +# the Free Software Foundation, either version 3 of the License, or |
534 | +# (at your option) any later version. |
535 | +# |
536 | +# This program is distributed in the hope that it will be useful, |
537 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
538 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
539 | +# GNU General Public License for more details. |
540 | +# |
541 | +# You should have received a copy of the GNU General Public License |
542 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
543 | +# |
544 | |
545 | === added file 'snappy_ecosystem_tests/configs/ecosystem_tests.cfg' |
546 | --- snappy_ecosystem_tests/configs/ecosystem_tests.cfg 1970-01-01 00:00:00 +0000 |
547 | +++ snappy_ecosystem_tests/configs/ecosystem_tests.cfg 2017-02-15 19:16:15 +0000 |
548 | @@ -0,0 +1,20 @@ |
549 | +[web-ui] |
550 | +browser=chrome |
551 | +stage_url=https://myapps.developer.staging.ubuntu.com/ |
552 | +production_url=https://myapps.developer.ubuntu.com/ |
553 | + |
554 | +[store] |
555 | +# store to use in tests. Possible values: staging or production |
556 | +environment=staging |
557 | + |
558 | +[staging_urls] |
559 | +root_api=https://myapps.developer.staging.ubuntu.com/dev/api/ |
560 | +upload=https://upload.apps.staging.ubuntu.com/ |
561 | +sso=https://login.staging.ubuntu.com/api/v2/ |
562 | +search=https://search.apps.staging.ubuntu.com/ |
563 | + |
564 | +[production_urls] |
565 | +root_api=https://myapps.developer.ubuntu.com/dev/api/ |
566 | +upload=https://upload.apps.ubuntu.com/ |
567 | +sso=https://login.ubuntu.com/api/v2/ |
568 | +search=https://search.apps.ubuntu.com/ |
569 | |
570 | === added file 'snappy_ecosystem_tests/configs/pytest.cfg' |
571 | --- snappy_ecosystem_tests/configs/pytest.cfg 1970-01-01 00:00:00 +0000 |
572 | +++ snappy_ecosystem_tests/configs/pytest.cfg 2017-02-15 19:16:15 +0000 |
573 | @@ -0,0 +1,2 @@ |
574 | +[pytest] |
575 | + |
576 | |
577 | === removed file 'snappy_ecosystem_tests/data/__init__.py' |
578 | --- snappy_ecosystem_tests/data/__init__.py 2017-02-07 17:41:23 +0000 |
579 | +++ snappy_ecosystem_tests/data/__init__.py 1970-01-01 00:00:00 +0000 |
580 | @@ -1,19 +0,0 @@ |
581 | -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
582 | - |
583 | -# |
584 | -# Snappy Ecosystem Tests |
585 | -# Copyright (C) 2017 Canonical |
586 | -# |
587 | -# This program is free software: you can redistribute it and/or modify |
588 | -# it under the terms of the GNU General Public License as published by |
589 | -# the Free Software Foundation, either version 3 of the License, or |
590 | -# (at your option) any later version. |
591 | -# |
592 | -# This program is distributed in the hope that it will be useful, |
593 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
594 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
595 | -# GNU General Public License for more details. |
596 | -# |
597 | -# You should have received a copy of the GNU General Public License |
598 | -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
599 | -# |
600 | |
601 | === added file 'snappy_ecosystem_tests/helpers/fixture_setup.py' |
602 | --- snappy_ecosystem_tests/helpers/fixture_setup.py 1970-01-01 00:00:00 +0000 |
603 | +++ snappy_ecosystem_tests/helpers/fixture_setup.py 2017-02-15 19:16:15 +0000 |
604 | @@ -0,0 +1,95 @@ |
605 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
606 | + |
607 | +# |
608 | +# Snappy Ecosystem Tests |
609 | +# Copyright (C) 2017 Canonical |
610 | +# |
611 | +# This program is free software: you can redistribute it and/or modify |
612 | +# it under the terms of the GNU General Public License as published by |
613 | +# the Free Software Foundation, either version 3 of the License, or |
614 | +# (at your option) any later version. |
615 | +# |
616 | +# This program is distributed in the hope that it will be useful, |
617 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
618 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
619 | +# GNU General Public License for more details. |
620 | +# |
621 | +# You should have received a copy of the GNU General Public License |
622 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
623 | +# |
624 | + |
625 | +"""Manage general tests fixtures""" |
626 | + |
627 | +import os |
628 | +import fixtures |
629 | +from snappy_ecosystem_tests.commons.config import CONFIG_STACK |
630 | +from snappy_ecosystem_tests.utils.storeconfig import get_current_store |
631 | + |
632 | + |
633 | +class TempCWD(fixtures.TempDir): |
634 | + """Create a temporary directory an cd into it for the test duration.""" |
635 | + |
636 | + def setUp(self): |
637 | + """Create a temporary directory an cd into it for the test duration.""" |
638 | + super().setUp() |
639 | + current_dir = os.getcwd() |
640 | + self.addCleanup(os.chdir, current_dir) |
641 | + os.chdir(self.path) |
642 | + |
643 | + |
644 | +class CleanEnvironment(fixtures.Fixture): |
645 | + """Clean all env variables and restore the original values as |
646 | + clean up process""" |
647 | + |
648 | + def setUp(self): |
649 | + super().setUp() |
650 | + |
651 | + current_environment = os.environ.copy() |
652 | + os.environ = {} |
653 | + |
654 | + self.addCleanup(os.environ.update, current_environment) |
655 | + |
656 | + |
657 | +class SetStoreEnvironmentVariables(fixtures.Fixture): |
658 | + """Configure the env variables for using staging urls""" |
659 | + |
660 | + def __init__(self, store): |
661 | + self.store = store |
662 | + |
663 | + def setUp(self): |
664 | + super().setUp() |
665 | + urls = CONFIG_STACK.get_section('%s_urls' % self.store) |
666 | + |
667 | + self.useFixture(fixtures.EnvironmentVariable( |
668 | + 'UBUNTU_STORE_API_ROOT_URL', |
669 | + urls.get('root_api'))) |
670 | + self.useFixture(fixtures.EnvironmentVariable( |
671 | + 'UBUNTU_STORE_UPLOAD_ROOT_URL', |
672 | + urls.get('upload'))) |
673 | + self.useFixture(fixtures.EnvironmentVariable( |
674 | + 'UBUNTU_SSO_API_ROOT_URL', |
675 | + urls.get('sso'))) |
676 | + self.useFixture(fixtures.EnvironmentVariable( |
677 | + 'UBUNTU_STORE_SEARCH_ROOT_URL', |
678 | + urls.get('search'))) |
679 | + |
680 | + |
681 | +class SetTestStore(fixtures.Fixture): |
682 | + """Configure the env variables for using the corresponding |
683 | + environment urls""" |
684 | + |
685 | + def __init__(self): |
686 | + self.register_delay = -1 |
687 | + |
688 | + def setUp(self): |
689 | + super().setUp() |
690 | + test_store = get_current_store() |
691 | + self.useFixture(SetStoreEnvironmentVariables(test_store)) |
692 | + if test_store == 'staging': |
693 | + self.register_delay = 10 |
694 | + elif test_store == 'production': |
695 | + # Use the default server URLs |
696 | + self.register_delay = 180 |
697 | + else: |
698 | + raise ValueError( |
699 | + 'Unknown test store option: {}'.format(test_store)) |
700 | |
701 | === added file 'snappy_ecosystem_tests/helpers/test_base.py' |
702 | --- snappy_ecosystem_tests/helpers/test_base.py 1970-01-01 00:00:00 +0000 |
703 | +++ snappy_ecosystem_tests/helpers/test_base.py 2017-02-15 19:16:15 +0000 |
704 | @@ -0,0 +1,32 @@ |
705 | +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- |
706 | +# |
707 | +# Copyright (C) 2017 Canonical Ltd |
708 | +# |
709 | +# This program is free software: you can redistribute it and/or modify |
710 | +# it under the terms of the GNU General Public License version 3 as |
711 | +# published by the Free Software Foundation. |
712 | +# |
713 | +# This program is distributed in the hope that it will be useful, |
714 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
715 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
716 | +# GNU General Public License for more details. |
717 | +# |
718 | +# You should have received a copy of the GNU General Public License |
719 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
720 | + |
721 | +"""Base Snappy Ecosystem test""" |
722 | + |
723 | +import testscenarios |
724 | +import testtools |
725 | +from snappy_ecosystem_tests.helpers import fixture_setup |
726 | +from snappy_ecosystem_tests.helpers.fixture_setup import SetTestStore |
727 | + |
728 | + |
729 | +class SnappyEcosystemTestCase(testscenarios.WithScenarios, testtools.TestCase): |
730 | + |
731 | + def setUp(self): |
732 | + super().setUp() |
733 | + temp_cwd_fixture = fixture_setup.TempCWD() |
734 | + self.useFixture(SetTestStore()) |
735 | + self.useFixture(temp_cwd_fixture) |
736 | + self.path = temp_cwd_fixture.path |
737 | |
738 | === removed file 'snappy_ecosystem_tests/helpers/ubuntu_store_tests_base.py' |
739 | --- snappy_ecosystem_tests/helpers/ubuntu_store_tests_base.py 2017-02-07 17:41:23 +0000 |
740 | +++ snappy_ecosystem_tests/helpers/ubuntu_store_tests_base.py 1970-01-01 00:00:00 +0000 |
741 | @@ -1,19 +0,0 @@ |
742 | -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
743 | - |
744 | -# |
745 | -# Snappy Ecosystem Tests |
746 | -# Copyright (C) 2017 Canonical |
747 | -# |
748 | -# This program is free software: you can redistribute it and/or modify |
749 | -# it under the terms of the GNU General Public License as published by |
750 | -# the Free Software Foundation, either version 3 of the License, or |
751 | -# (at your option) any later version. |
752 | -# |
753 | -# This program is distributed in the hope that it will be useful, |
754 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
755 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
756 | -# GNU General Public License for more details. |
757 | -# |
758 | -# You should have received a copy of the GNU General Public License |
759 | -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
760 | -# |
761 | |
762 | === renamed file 'snappy_ecosystem_tests/helpers/ubuntu_store_web_test_base.py' => 'snappy_ecosystem_tests/helpers/web_test_base.py' |
763 | --- snappy_ecosystem_tests/helpers/ubuntu_store_web_test_base.py 2017-02-07 17:49:25 +0000 |
764 | +++ snappy_ecosystem_tests/helpers/web_test_base.py 2017-02-15 19:16:15 +0000 |
765 | @@ -19,8 +19,7 @@ |
766 | # |
767 | |
768 | """Web-Ui related functionality for testing web pages using selenium""" |
769 | - |
770 | -import unittest |
771 | +import logging |
772 | |
773 | from selenium import webdriver |
774 | from selenium.webdriver.support.ui import WebDriverWait |
775 | @@ -28,7 +27,10 @@ |
776 | from selenium.common.exceptions import TimeoutException |
777 | from selenium.webdriver.common.by import By |
778 | |
779 | -from snappy_ecosystem_tests import storeconfig |
780 | +from snappy_ecosystem_tests.utils import storeconfig |
781 | +from snappy_ecosystem_tests.helpers.test_base import SnappyEcosystemTestCase |
782 | + |
783 | +LOGGER = logging.getLogger(__name__) |
784 | |
785 | LOGIN_EMAIL, LOGIN_PASSWORD = storeconfig.get_store_credentials() |
786 | STORE_URL = storeconfig.get_store_web_url() |
787 | @@ -37,12 +39,16 @@ |
788 | PAGE_LOAD_TIMEOUT = 30 |
789 | |
790 | |
791 | -class UbuntuStoreWebTestsBase(unittest.TestCase): |
792 | +class UbuntuStoreWebTestsBase(SnappyEcosystemTestCase): |
793 | """Base class to represent a Web-UI test case. |
794 | - Contain basic functionality for locating web elements and interacting with a page |
795 | + Contain basic functionality for locating web elements and |
796 | + interacting with a page |
797 | """ |
798 | + |
799 | def setUp(self): |
800 | - # TODO - add support for multiple type browsers including Chrome, FF and IE |
801 | + # TODO - add support for multiple type browsers including Chrome, |
802 | + # FF and IE |
803 | + super().setUp() |
804 | options = webdriver.ChromeOptions() |
805 | options.add_argument("--start-maximized") |
806 | self.driver = webdriver.Chrome(chrome_options=options) |
807 | @@ -55,7 +61,8 @@ |
808 | element_present = EC.presence_of_element_located(locator) |
809 | wait.until(element_present) |
810 | except TimeoutException: |
811 | - print("Timed out waiting for "+locator[1]+" page") |
812 | + LOGGER.error("Timed out waiting for " + locator[1] + " page") |
813 | + raise |
814 | |
815 | def wait_for_page_title(self, title, timeout=PAGE_LOAD_TIMEOUT): |
816 | """Wait for the target page title for given timeout, |
817 | @@ -65,7 +72,8 @@ |
818 | find_title = EC.title_is(title) |
819 | wait.until(find_title) |
820 | except TimeoutException: |
821 | - print("Timed out waiting for "+title + " page") |
822 | + LOGGER.error("Timed out waiting for " + title + " page") |
823 | + raise |
824 | |
825 | def wait_for_visible(self, timeout=PAGE_LOAD_TIMEOUT): |
826 | # TODO: re-implement to allow any locator as parameter |
827 | @@ -77,7 +85,8 @@ |
828 | (By.XPATH, "/html/body/nav/div/div[1]/span")) |
829 | wait.until(element_visible) |
830 | except TimeoutException: |
831 | - print("Timed out waiting for element to be visible") |
832 | + LOGGER.error("Timed out waiting for element to be visible") |
833 | + raise |
834 | |
835 | def wait_for_clickable(self, timeout=PAGE_LOAD_TIMEOUT): |
836 | # TODO: re-implement to allow any locator as parameter |
837 | @@ -89,10 +98,12 @@ |
838 | (By.XPATH, "/html/body/nav/div/div[1]/span")) |
839 | wait.until(element_clickable) |
840 | except TimeoutException: |
841 | - print("Timed out waiting for element to be clickable") |
842 | + LOGGER.error("Timed out waiting for element to be clickable") |
843 | + raise |
844 | |
845 | def login(self): |
846 | - """Login to web interface, following the UI flow which end user would use""" |
847 | + """Login to web interface, following the UI flow which end user |
848 | + would use""" |
849 | driver = self.driver |
850 | driver.get(STORE_URL) |
851 | |
852 | @@ -111,28 +122,34 @@ |
853 | self.wait_for_page_title("Your packages") |
854 | |
855 | def logout(self): |
856 | - """Logout of web interface, following the UI flow which end user would use""" |
857 | + """Logout of web interface, following the UI flow which end |
858 | + user would use""" |
859 | driver = self.driver |
860 | self.wait_for_element((By.CLASS_NAME, "b-dropdown__arrow_light")) |
861 | # |
862 | - # extremely ugly way to reach the desired element by xpath, a bug will be |
863 | + # extremely ugly way to reach the desired element by xpath, |
864 | + # a bug will be |
865 | # raised to uniquely identify the dropdown arrows |
866 | self.wait_for_clickable() |
867 | - down_arrow = driver.find_element_by_xpath("/html/body/nav/div/div[1]/span") |
868 | + down_arrow = driver.find_element_by_xpath( |
869 | + "/html/body/nav/div/div[1]/span") |
870 | # |
871 | # There is a bug with Firefox webdriver when clicking elements, |
872 | # as sometime click doesn't have any effect, to workaround that |
873 | - # multiple attempts are made. However everything works fine with chrome webdriver. |
874 | + # multiple attempts are made. However everything works fine with |
875 | + # chrome webdriver. |
876 | |
877 | for _ in range(0, 2): |
878 | wait = WebDriverWait(self.driver, 1) |
879 | try: |
880 | down_arrow.click() |
881 | - element_present = EC.presence_of_element_located((By.CLASS_NAME, "b-dropdown_open")) |
882 | + element_present = EC.presence_of_element_located( |
883 | + (By.CLASS_NAME, "b-dropdown_open")) |
884 | wait.until(element_present) |
885 | break |
886 | except TimeoutException: |
887 | - print("Failed to open the accounts dropdown menu card, Trying again") |
888 | + LOGGER.error("Failed to open the accounts dropdown menu card," |
889 | + " Trying again") |
890 | |
891 | self.wait_for_visible() |
892 | logout_link = driver.find_element_by_link_text("Log out") |
893 | @@ -141,5 +158,6 @@ |
894 | self.wait_for_page_title("Sign in to see your packages") |
895 | |
896 | def tearDown(self): |
897 | + super().tearDown() |
898 | self.driver.close() |
899 | self.driver.quit() |
900 | |
901 | === added file 'snappy_ecosystem_tests/run.py' |
902 | --- snappy_ecosystem_tests/run.py 1970-01-01 00:00:00 +0000 |
903 | +++ snappy_ecosystem_tests/run.py 2017-02-15 19:16:15 +0000 |
904 | @@ -0,0 +1,47 @@ |
905 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
906 | + |
907 | +# |
908 | +# Snappy Ecosystem Tests |
909 | +# Copyright (C) 2017 Canonical |
910 | +# |
911 | +# This program is free software: you can redistribute it and/or modify |
912 | +# it under the terms of the GNU General Public License as published by |
913 | +# the Free Software Foundation, either version 3 of the License, or |
914 | +# (at your option) any later version. |
915 | +# |
916 | +# This program is distributed in the hope that it will be useful, |
917 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
918 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
919 | +# GNU General Public License for more details. |
920 | +# |
921 | +# You should have received a copy of the GNU General Public License |
922 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
923 | +# |
924 | + |
925 | +"""Entry point to run snappy ecosystem tests""" |
926 | + |
927 | +import re |
928 | +import sys |
929 | +import pytest |
930 | + |
931 | +FILTER_ARGUMENTS = '--proxy' |
932 | + |
933 | + |
934 | +def _filter_arguments(): |
935 | + """Remove from command line arguments all the ones that are in |
936 | + FILTER_ARGUMENTS list.""" |
937 | + filtered_args = sys.argv[1:] |
938 | + for i, arg in enumerate(sys.argv[1:]): |
939 | + if arg in FILTER_ARGUMENTS: |
940 | + filtered_args.pop(i + 1) |
941 | + filtered_args.pop(i) |
942 | + return filtered_args |
943 | + |
944 | + |
945 | +def _parse_arguments(): |
946 | + """Parse and filter command line arguments to makethem pytest compatible""" |
947 | + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) |
948 | + return _filter_arguments() |
949 | + |
950 | +if __name__ == '__main__': |
951 | + sys.exit(pytest.main(args=_parse_arguments() + ['-p', 'no:cacheprovider'])) |
952 | |
953 | === added directory 'snappy_ecosystem_tests/snapcraft' |
954 | === added file 'snappy_ecosystem_tests/snapcraft/__init__.py' |
955 | --- snappy_ecosystem_tests/snapcraft/__init__.py 1970-01-01 00:00:00 +0000 |
956 | +++ snappy_ecosystem_tests/snapcraft/__init__.py 2017-02-15 19:16:15 +0000 |
957 | @@ -0,0 +1,19 @@ |
958 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
959 | + |
960 | +# |
961 | +# Snappy Ecosystem Tests |
962 | +# Copyright (C) 2017 Canonical |
963 | +# |
964 | +# This program is free software: you can redistribute it and/or modify |
965 | +# it under the terms of the GNU General Public License as published by |
966 | +# the Free Software Foundation, either version 3 of the License, or |
967 | +# (at your option) any later version. |
968 | +# |
969 | +# This program is distributed in the hope that it will be useful, |
970 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
971 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
972 | +# GNU General Public License for more details. |
973 | +# |
974 | +# You should have received a copy of the GNU General Public License |
975 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
976 | +# |
977 | |
978 | === renamed file 'snappy_ecosystem_tests/utils/snapcraft.py' => 'snappy_ecosystem_tests/snapcraft/snapcraft.py' |
979 | --- snappy_ecosystem_tests/utils/snapcraft.py 2017-02-07 17:49:25 +0000 |
980 | +++ snappy_ecosystem_tests/snapcraft/snapcraft.py 2017-02-15 19:16:15 +0000 |
981 | @@ -18,43 +18,23 @@ |
982 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
983 | # |
984 | |
985 | -"""Snapcraft related helpers to configure the snapcraft environment: staging or production |
986 | -and other specific functions inside Snapcraft class |
987 | -""" |
988 | +"""Snapcraft client helpers""" |
989 | |
990 | -import os |
991 | import pexpect |
992 | |
993 | |
994 | # login credentials exported by shell environment |
995 | -from snappy_ecosystem_tests import storeconfig |
996 | +from snappy_ecosystem_tests.utils import storeconfig |
997 | |
998 | LOGIN_EMAIL, LOGIN_PASSWORD = storeconfig.get_store_credentials() |
999 | |
1000 | |
1001 | -def set_snapcraft_environment(): |
1002 | - """set the environment variables for snapcraft communication with store, |
1003 | - this will be staging by default. if STAGING environment variable is |
1004 | - set to 0, then it will be set to production""" |
1005 | - if storeconfig.is_staging(): |
1006 | - os.environ["UBUNTU_STORE_SEARCH_ROOT_URL"] = 'https://search.apps.staging.ubuntu.com/' |
1007 | - os.environ["UBUNTU_STORE_UPLOAD_ROOT_URL"] = 'https://upload.apps.staging.ubuntu.com/' |
1008 | - os.environ["UBUNTU_SSO_API_ROOT_URL"] = 'https://login.staging.ubuntu.com/api/v2/' |
1009 | - os.environ["UBUNTU_STORE_API_ROOT_URL"] = \ |
1010 | - 'https://myapps.developer.staging.ubuntu.com/dev/api/' |
1011 | - else: |
1012 | - os.environ["UBUNTU_STORE_SEARCH_ROOT_URL"] = 'https://search.apps.ubuntu.com/' |
1013 | - os.environ["UBUNTU_STORE_UPLOAD_ROOT_URL"] = 'https://upload.apps.ubuntu.com/' |
1014 | - os.environ["UBUNTU_SSO_API_ROOT_URL"] = 'https://login.ubuntu.com/api/v2/' |
1015 | - os.environ["UBUNTU_STORE_API_ROOT_URL"] = 'https://myapps.developer.ubuntu.com/dev/api/' |
1016 | - |
1017 | - |
1018 | class Snapcraft(object): |
1019 | - """Contain Snapcraft specific functionality to use via command line interface""" |
1020 | + """Contain Snapcraft specific functionality to use via command |
1021 | + line interface""" |
1022 | def __init__(self): |
1023 | """Create new snapcraft instance.""" |
1024 | self._login = False |
1025 | - set_snapcraft_environment() |
1026 | self._cleanup() |
1027 | |
1028 | def _cleanup(self): |
1029 | @@ -86,7 +66,9 @@ |
1030 | self._login = True |
1031 | |
1032 | def list_registered(self): |
1033 | - """call snapcraft list-registered command, raise exception if not logged in""" |
1034 | + """call snapcraft list-registered command, |
1035 | + raise exception if not logged in""" |
1036 | if self._login is False: |
1037 | - raise ValueError("User is not logged in, please login before using this command") |
1038 | + raise ValueError("User is not logged in, " |
1039 | + "please login before using this command") |
1040 | return pexpect.spawnu("snapcraft list-registered").read() |
1041 | |
1042 | === added directory 'snappy_ecosystem_tests/snapd' |
1043 | === added file 'snappy_ecosystem_tests/snapd/__init__.py' |
1044 | --- snappy_ecosystem_tests/snapd/__init__.py 1970-01-01 00:00:00 +0000 |
1045 | +++ snappy_ecosystem_tests/snapd/__init__.py 2017-02-15 19:16:15 +0000 |
1046 | @@ -0,0 +1,19 @@ |
1047 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1048 | + |
1049 | +# |
1050 | +# Snappy Ecosystem Tests |
1051 | +# Copyright (C) 2017 Canonical |
1052 | +# |
1053 | +# This program is free software: you can redistribute it and/or modify |
1054 | +# it under the terms of the GNU General Public License as published by |
1055 | +# the Free Software Foundation, either version 3 of the License, or |
1056 | +# (at your option) any later version. |
1057 | +# |
1058 | +# This program is distributed in the hope that it will be useful, |
1059 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1060 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1061 | +# GNU General Public License for more details. |
1062 | +# |
1063 | +# You should have received a copy of the GNU General Public License |
1064 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1065 | +# |
1066 | |
1067 | === renamed file 'snappy_ecosystem_tests/utils/snapd.py' => 'snappy_ecosystem_tests/snapd/snapd.py' |
1068 | === added directory 'snappy_ecosystem_tests/tests' |
1069 | === removed directory 'snappy_ecosystem_tests/tests' |
1070 | === added file 'snappy_ecosystem_tests/tests/__init__.py' |
1071 | --- snappy_ecosystem_tests/tests/__init__.py 1970-01-01 00:00:00 +0000 |
1072 | +++ snappy_ecosystem_tests/tests/__init__.py 2017-02-15 19:16:15 +0000 |
1073 | @@ -0,0 +1,19 @@ |
1074 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1075 | + |
1076 | +# |
1077 | +# Snappy Ecosystem Tests |
1078 | +# Copyright (C) 2017 Canonical |
1079 | +# |
1080 | +# This program is free software: you can redistribute it and/or modify |
1081 | +# it under the terms of the GNU General Public License as published by |
1082 | +# the Free Software Foundation, either version 3 of the License, or |
1083 | +# (at your option) any later version. |
1084 | +# |
1085 | +# This program is distributed in the hope that it will be useful, |
1086 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1087 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1088 | +# GNU General Public License for more details. |
1089 | +# |
1090 | +# You should have received a copy of the GNU General Public License |
1091 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1092 | +# |
1093 | |
1094 | === removed file 'snappy_ecosystem_tests/tests/__init__.py' |
1095 | --- snappy_ecosystem_tests/tests/__init__.py 2017-02-07 17:49:25 +0000 |
1096 | +++ snappy_ecosystem_tests/tests/__init__.py 1970-01-01 00:00:00 +0000 |
1097 | @@ -1,19 +0,0 @@ |
1098 | -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1099 | - |
1100 | -# |
1101 | -# Snappy Ecosystem Tests |
1102 | -# Copyright (C) 2017 Canonical |
1103 | -# |
1104 | -# This program is free software: you can redistribute it and/or modify |
1105 | -# it under the terms of the GNU General Public License as published by |
1106 | -# the Free Software Foundation, either version 3 of the License, or |
1107 | -# (at your option) any later version. |
1108 | -# |
1109 | -# This program is distributed in the hope that it will be useful, |
1110 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1111 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1112 | -# GNU General Public License for more details. |
1113 | -# |
1114 | -# You should have received a copy of the GNU General Public License |
1115 | -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1116 | -# |
1117 | |
1118 | === renamed directory 'snappy_ecosystem_tests/data' => 'snappy_ecosystem_tests/tests/data' |
1119 | === added directory 'snappy_ecosystem_tests/tests/data/entity' |
1120 | === added file 'snappy_ecosystem_tests/tests/data/entity/entity.json' |
1121 | --- snappy_ecosystem_tests/tests/data/entity/entity.json 1970-01-01 00:00:00 +0000 |
1122 | +++ snappy_ecosystem_tests/tests/data/entity/entity.json 2017-02-15 19:16:15 +0000 |
1123 | @@ -0,0 +1,6 @@ |
1124 | +{ |
1125 | + "entity": [ |
1126 | + { |
1127 | + } |
1128 | + ] |
1129 | +} |
1130 | \ No newline at end of file |
1131 | |
1132 | === renamed file 'snappy_ecosystem_tests/test_store_login.py' => 'snappy_ecosystem_tests/tests/test_store_login.py' |
1133 | --- snappy_ecosystem_tests/test_store_login.py 2017-02-07 19:44:37 +0000 |
1134 | +++ snappy_ecosystem_tests/tests/test_store_login.py 2017-02-15 19:16:15 +0000 |
1135 | @@ -20,11 +20,12 @@ |
1136 | |
1137 | """Test for Login to the Store via Web Interface, snapcraft and snapd""" |
1138 | |
1139 | -from snappy_ecosystem_tests.utils.snapcraft import Snapcraft |
1140 | -from snappy_ecosystem_tests.helpers.ubuntu_store_web_test_base import UbuntuStoreWebTestsBase |
1141 | +from snappy_ecosystem_tests.snapcraft.snapcraft import Snapcraft |
1142 | +from snappy_ecosystem_tests.helpers.web_test_base import UbuntuStoreWebTestsBase |
1143 | |
1144 | |
1145 | class StoreLoginTestCase(UbuntuStoreWebTestsBase): |
1146 | + |
1147 | def setUp(self): |
1148 | super().setUp() |
1149 | |
1150 | @@ -40,7 +41,8 @@ |
1151 | |
1152 | self.login() |
1153 | self.assertEqual(self.driver.title, "Your packages", "Failed to login") |
1154 | - # TODO - fragile as there is no unique way to identify the dropdown arrow |
1155 | + # TODO - fragile as there is no unique way to identify |
1156 | + # the dropdown arrow |
1157 | self.logout() |
1158 | self.assertEqual( |
1159 | self.driver.title, "Sign in to see your packages", |
1160 | |
1161 | === modified file 'snappy_ecosystem_tests/unittests/test_snapcraft.py' |
1162 | --- snappy_ecosystem_tests/unittests/test_snapcraft.py 2017-02-10 20:22:24 +0000 |
1163 | +++ snappy_ecosystem_tests/unittests/test_snapcraft.py 2017-02-15 19:16:15 +0000 |
1164 | @@ -22,8 +22,10 @@ |
1165 | |
1166 | from unittest2 import TestCase |
1167 | |
1168 | + |
1169 | class SnapcraftTestCase(TestCase): |
1170 | |
1171 | def test_snapcraft_dummy_test(self): |
1172 | """Dummy test case""" |
1173 | - self.assertTrue(True) |
1174 | + _a = True |
1175 | + self.assertTrue(_a) |
1176 | |
1177 | === added file 'snappy_ecosystem_tests/utils/json.py' |
1178 | --- snappy_ecosystem_tests/utils/json.py 1970-01-01 00:00:00 +0000 |
1179 | +++ snappy_ecosystem_tests/utils/json.py 2017-02-15 19:16:15 +0000 |
1180 | @@ -0,0 +1,30 @@ |
1181 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1182 | + |
1183 | +# |
1184 | +# Snappy Ecosystem Tests |
1185 | +# Copyright (C) 2017 Canonical |
1186 | +# |
1187 | +# This program is free software: you can redistribute it and/or modify |
1188 | +# it under the terms of the GNU General Public License as published by |
1189 | +# the Free Software Foundation, either version 3 of the License, or |
1190 | +# (at your option) any later version. |
1191 | +# |
1192 | +# This program is distributed in the hope that it will be useful, |
1193 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1194 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1195 | +# GNU General Public License for more details. |
1196 | +# |
1197 | +# You should have received a copy of the GNU General Public License |
1198 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1199 | +# |
1200 | + |
1201 | +"""Manage json files""" |
1202 | + |
1203 | +import json |
1204 | + |
1205 | + |
1206 | +def read_json_from_file(file_path): |
1207 | + """Read a json from the given file path and return it as a dict""" |
1208 | + with open(file_path) as _f: |
1209 | + data_json = json.load(_f) |
1210 | + return data_json |
1211 | |
1212 | === added file 'snappy_ecosystem_tests/utils/singleton.py' |
1213 | --- snappy_ecosystem_tests/utils/singleton.py 1970-01-01 00:00:00 +0000 |
1214 | +++ snappy_ecosystem_tests/utils/singleton.py 2017-02-15 19:16:15 +0000 |
1215 | @@ -0,0 +1,38 @@ |
1216 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1217 | + |
1218 | +# |
1219 | +# Snappy Ecosystem Tests |
1220 | +# Copyright (C) 2017 Canonical |
1221 | +# |
1222 | +# This program is free software: you can redistribute it and/or modify |
1223 | +# it under the terms of the GNU General Public License as published by |
1224 | +# the Free Software Foundation, either version 3 of the License, or |
1225 | +# (at your option) any later version. |
1226 | +# |
1227 | +# This program is distributed in the hope that it will be useful, |
1228 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1229 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1230 | +# GNU General Public License for more details. |
1231 | +# |
1232 | +# You should have received a copy of the GNU General Public License |
1233 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1234 | +# |
1235 | + |
1236 | +"""Singleton utils""" |
1237 | + |
1238 | + |
1239 | +class Singleton(type): |
1240 | + """Class that represents a singleton entity. |
1241 | + Usage: Specify metaclass=Singleton in those classes you want to be |
1242 | + Singleton. |
1243 | + Example: MyClass(metaclass=Singleton). |
1244 | + And automatically the same instance will be returned when creating |
1245 | + MyClass objects. |
1246 | + """ |
1247 | + __instances = {} |
1248 | + |
1249 | + def __call__(cls, *args, **kwargs): |
1250 | + if cls not in cls.__instances: |
1251 | + cls.__instances[cls] = super(Singleton, cls).__call__( |
1252 | + *args, **kwargs) |
1253 | + return cls.__instances[cls] |
1254 | |
1255 | === renamed file 'snappy_ecosystem_tests/storeconfig.py' => 'snappy_ecosystem_tests/utils/storeconfig.py' |
1256 | --- snappy_ecosystem_tests/storeconfig.py 2017-02-07 17:41:23 +0000 |
1257 | +++ snappy_ecosystem_tests/utils/storeconfig.py 2017-02-15 19:16:15 +0000 |
1258 | @@ -18,25 +18,34 @@ |
1259 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
1260 | # |
1261 | |
1262 | -"""Helpers to retrieve store configuration data like: credentials, urls, etc""" |
1263 | +"""Get all the store related data like credentials, urls""" |
1264 | |
1265 | import os |
1266 | |
1267 | -KEY_ENVIRON_STORE_LOGIN_EMAIL = 'UBUNTU_STORE_LOGIN_EMAIL' |
1268 | -KEY_ENVIRON_STORE_LOGIN_PASSWORD = 'UBUNTU_STORE_LOGIN_PASSWORD' |
1269 | -URL_WEB_STORE_PRODUCTION = 'https://myapps.developer.ubuntu.com/' |
1270 | -URL_WEB_STORE_STAGING = 'https://myapps.developer.staging.ubuntu.com/' |
1271 | +from snappy_ecosystem_tests.commons.config import ( |
1272 | + CONFIG_STACK, |
1273 | + USER_CONFIG_STACK |
1274 | +) |
1275 | + |
1276 | +URL_WEB_STORE_PRODUCTION = CONFIG_STACK.get('web-ui', 'production_url') |
1277 | +URL_WEB_STORE_STAGING = CONFIG_STACK.get('web-ui', 'stage_url') |
1278 | |
1279 | |
1280 | def get_store_credentials(): |
1281 | - """login credentials exported by shell environment""" |
1282 | - return os.environ['UBUNTU_STORE_LOGIN_EMAIL'], \ |
1283 | - os.environ['UBUNTU_STORE_LOGIN_PASSWORD'] |
1284 | + """Get user store credentials. |
1285 | + It will retrieve the credentials stored in a user config file, |
1286 | + if the config is not found, |
1287 | + then it will return the ones provided in environment variables |
1288 | + """ |
1289 | + return (USER_CONFIG_STACK.get('user', 'user_email', |
1290 | + default=os.environ.get('user_email')), |
1291 | + USER_CONFIG_STACK.get('user', 'user_password', |
1292 | + default=os.environ.get('user_password'))) |
1293 | |
1294 | |
1295 | def is_staging(): |
1296 | """Return False if environment variable PROD is exported""" |
1297 | - return os.environ.get('STAGING', "1") == "1" |
1298 | + return get_current_store() == 'staging' |
1299 | |
1300 | |
1301 | def get_store_web_url(): |
1302 | @@ -44,3 +53,14 @@ |
1303 | if optional staging argument is false then it will return |
1304 | production server url """ |
1305 | return URL_WEB_STORE_STAGING if is_staging() else URL_WEB_STORE_PRODUCTION |
1306 | + |
1307 | + |
1308 | +def get_current_store(): |
1309 | + """ |
1310 | + Return the current configured store. It will first read the config value, |
1311 | + if no config value is set, it will read the env variable TEST_STORE, |
1312 | + if that env variable is not set, then it returns staging as default |
1313 | + :return: current configured store environment |
1314 | + """ |
1315 | + return CONFIG_STACK.get('store', 'environment', |
1316 | + os.getenv('TEST_STORE', 'staging')) |
1317 | |
1318 | === added file 'snappy_ecosystem_tests/utils/test_data.py' |
1319 | --- snappy_ecosystem_tests/utils/test_data.py 1970-01-01 00:00:00 +0000 |
1320 | +++ snappy_ecosystem_tests/utils/test_data.py 2017-02-15 19:16:15 +0000 |
1321 | @@ -0,0 +1,46 @@ |
1322 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1323 | + |
1324 | +# |
1325 | +# Snappy Ecosystem Tests |
1326 | +# Copyright (C) 2017 Canonical |
1327 | +# |
1328 | +# This program is free software: you can redistribute it and/or modify |
1329 | +# it under the terms of the GNU General Public License as published by |
1330 | +# the Free Software Foundation, either version 3 of the License, or |
1331 | +# (at your option) any later version. |
1332 | +# |
1333 | +# This program is distributed in the hope that it will be useful, |
1334 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1335 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1336 | +# GNU General Public License for more details. |
1337 | +# |
1338 | +# You should have received a copy of the GNU General Public License |
1339 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1340 | +# |
1341 | + |
1342 | +"""Parse and get all tests data that will be used during test execution""" |
1343 | + |
1344 | +import os |
1345 | + |
1346 | +from snappy_ecosystem_tests.utils.json import read_json_from_file |
1347 | + |
1348 | +# Test data dirs |
1349 | +DIR_TESTS = os.path.realpath(__file__ + '/../../tests') |
1350 | +DIR_TEST_DATA = os.path.join(DIR_TESTS, 'data') |
1351 | +DIR_TEST_DATA_ENTITY = os.path.join(DIR_TEST_DATA, 'entity') |
1352 | + |
1353 | +# Test data files |
1354 | +ENTITY_FILE = os.path.join(DIR_TEST_DATA_ENTITY, 'entity.json') |
1355 | + |
1356 | + |
1357 | +class EntityStack: |
1358 | + """Class store an entity that is read as |
1359 | + test data in json files""" |
1360 | + |
1361 | + def __init__(self): |
1362 | + self.__entities = read_json_from_file(ENTITY_FILE) |
1363 | + |
1364 | + @property |
1365 | + def entities(self): |
1366 | + """Get the current entities""" |
1367 | + return self.__entities |
FAILED: Continuous integration, rev:14 /platform- qa-jenkins. ubuntu. com/job/ snappy- ecosystem- tests-ci/ 25/ /platform- qa-jenkins. ubuntu. com/job/ generic- update- mp/1602/ console
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild: /platform- qa-jenkins. ubuntu. com/job/ snappy- ecosystem- tests-ci/ 25/rebuild
https:/