Merge lp:~elopio/canonical-identity-provider/refactory_with_u1testutils-1 into lp:canonical-identity-provider/release
- refactory_with_u1testutils-1
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Leo Arias |
Approved revision: | no longer in the source branch. |
Merged at revision: | 811 |
Proposed branch: | lp:~elopio/canonical-identity-provider/refactory_with_u1testutils-1 |
Merge into: | lp:canonical-identity-provider/release |
Diff against target: |
378 lines (+155/-72) 6 files modified
identityprovider/tests/acceptance/devices/add_device.py (+1/-4) identityprovider/tests/acceptance/pages.py (+94/-0) identityprovider/tests/acceptance/shared/helpers.py (+56/-64) requirements/testing.txt (+2/-2) scripts/acceptance-dev.sh (+1/-1) scripts/run-acceptance-tests (+1/-1) |
To merge this branch: | bzr merge lp:~elopio/canonical-identity-provider/refactory_with_u1testutils-1 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ricardo Kirkner (community) | Approve | ||
Review via email: mp+158722@code.launchpad.net |
Commit message
Use page object on the common acceptance helpers.
Description of the change
This is the first safe point of the refactor. I haven't changed any API, so there are some things left TODO.
In the next branches we will be deprecating this helpers, in favor of base test cases that will do all the page navigation and the tests will need to focus only on one or two pages.
Leo Arias (elopio) wrote : | # |
Leo Arias (elopio) wrote : | # |
$ ./scripts/
-------
Ran 110 tests in 1308.872s
OK
Save again :)
Leo Arias (elopio) wrote : | # |
This branch requires https:/
Ricardo Kirkner (ricardokirkner) wrote : | # |
l. 35,37: no need to have the extra whitespace
l. 53: we could be using the new data-qa-id attrs for looking up elements (for better disambiguation)
l. 365,378: why did you remove the extended=true param?
Ricardo Kirkner (ricardokirkner) wrote : | # |
l. 19-20, we could replace this with helpers.
Leo Arias (elopio) wrote : | # |
I removed the extended=true because it prints the page on the test log. The htmls are huge, so it doesn't help understanding what's wrong. We get the html with screenshot=True. I filed a bug on SST to change the name of that parameter.
Leo Arias (elopio) wrote : | # |
<elopio> pindonga: I was planning to add the data-qa-id's in next branches, as I wanted this just to be a reorg of the actions.
<elopio> can I leave it like this?
<elopio> pindonga: and I removed the extended=true because it prints the page on the test log.
<pindonga> yup, comment that on the mp though pls
Ricardo Kirkner (ricardokirkner) wrote : | # |
Despite the resistance to nit-picking, LGTM. Many things are being changed in a subsequent MP according to elopio, so not worth changing right now.
Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
The attempt to merge lp:~elopio/canonical-identity-provider/refactory_with_u1testutils-1 into lp:canonical-identity-provider failed. Below is the output from the failed tests.
Updating download cache at dir /mnt/tarmac/
Using saved parent location: bzr+ssh:
No revisions or tags to pull.
[localhost] local: which virtualenv
[localhost] local: /usr/bin/python /usr/bin/virtualenv --version
[localhost] local: /usr/bin/python /usr/bin/virtualenv --distribute --clear .env
Not deleting .env/bin
New python executable in .env/bin/python
Installing distribute.
Installing pip....
[localhost] local: dpkg -l libpq-dev 2> /dev/null | grep '^ii' | wc -l
[localhost] local: dpkg -l libxml2-dev 2> /dev/null | grep '^ii' | wc -l
[localhost] local: dpkg -l libxslt1-dev 2> /dev/null | grep '^ii' | wc -l
[localhost] local: dpkg -l memcached 2> /dev/null | grep '^ii' | wc -l
[localhost] local: dpkg -l postgresql-
[localhost] local: dpkg -l python-dev 2> /dev/null | grep '^ii' | wc -l
[localhost] local: dpkg -l python-m2crypto 2> /dev/null | grep '^ii' | wc -l
[localhost] local: dpkg -l swig 2> /dev/null | grep '^ii' | wc -l
[localhost] local: dpkg -l config-manager 2> /dev/null | grep '^ii' | wc -l
[localhost] local: dpkg -l python-
[localhost] local: rm -rf M2Crypto*
[localhost] local: ln -s /usr/lib/
[localhost] local: /usr/lib/
[localhost] local: . /mnt/tarmac/
pip install --find-
Ignoring indexes: http://
Downloading/
Running setup.py egg_info for package pip
warning: no files found matching '*.html' under directory 'docs'
warning: no previously-included files matching '*.txt' found under directory 'docs/_build'
no previously-included directories found matching 'docs/_
Installing collected packages: pip
Found existing installation: pip 1.1
Uninstalling pip:
Successfully uninstalled pip
Running setup.py install for pip
warning: no files found matching '*.html' under directory 'docs'
warning: no previously-included files matching '*.txt' found under directory 'docs/_build'
no previously-included directories found matching 'docs/_
Installing pip script to /mnt/tarmac/
Installing pip-2.7 script to /mnt/tarmac/
Successfully installed pip
Cleaning up...
pip install --find-links=. --no-index -r /mnt/tarmac/
Ignoring indexes: http://
Preview Diff
1 | === modified file 'identityprovider/tests/acceptance/devices/add_device.py' |
2 | --- identityprovider/tests/acceptance/devices/add_device.py 2013-01-24 17:02:52 +0000 |
3 | +++ identityprovider/tests/acceptance/devices/add_device.py 2013-04-19 19:28:26 +0000 |
4 | @@ -15,8 +15,6 @@ |
5 | get_element, |
6 | go_to, |
7 | set_radio_value, |
8 | - start, |
9 | - stop, |
10 | write_textfield, |
11 | ) |
12 | from u1testutils.sst import config |
13 | @@ -126,8 +124,7 @@ |
14 | |
15 | # Stop the browser and restart to ensure 2F Flag is still set |
16 | # Tests defect #930377 |
17 | -stop() |
18 | -start() |
19 | +helpers.logout() |
20 | helpers.login() |
21 | go_to(urls.DEVICES) |
22 | |
23 | |
24 | === added file 'identityprovider/tests/acceptance/pages.py' |
25 | --- identityprovider/tests/acceptance/pages.py 1970-01-01 00:00:00 +0000 |
26 | +++ identityprovider/tests/acceptance/pages.py 2013-04-19 19:28:26 +0000 |
27 | @@ -0,0 +1,94 @@ |
28 | +# Copyright 2013 Canonical Ltd. |
29 | +# This software is licensed under the GNU Affero General Public License |
30 | +# version 3 (see the file LICENSE). |
31 | + |
32 | +import logging |
33 | + |
34 | +import sst.actions |
35 | +import u1testutils.sso.sst.pages |
36 | + |
37 | +from u1testutils.sst import log_action |
38 | + |
39 | + |
40 | +class YourEmailAddresses(u1testutils.sso.sst.pages.PageWithUserSubheader): |
41 | + |
42 | + title = "{0}'s email addresses" |
43 | + url_path = '/+emails' |
44 | + |
45 | + def assert_title(self): |
46 | + user_name = self.subheader.get_user_name() |
47 | + sst.actions.assert_title(self.title.format(user_name)) |
48 | + |
49 | + @log_action(logging.info) |
50 | + def add_email(self, email_address): |
51 | + sst.actions.write_textfield('id_newemail', email_address) |
52 | + sst.actions.click_button(sst.actions.get_element(name='continue')) |
53 | + |
54 | + @log_action(logging.info) |
55 | + def delete_email(self): |
56 | + remove_link = sst.actions.get_element(tag='a', text='Delete') |
57 | + sst.actions.click_link(remove_link) |
58 | + return DeleteEmail() |
59 | + |
60 | + |
61 | +class EnterConfirmationCode(u1testutils.sso.sst.pages.PageWithUserSubheader): |
62 | + |
63 | + title = 'Enter confirmation code' |
64 | + url_path = '/+enter_token' |
65 | + |
66 | + @log_action(logging.info) |
67 | + def confirm(self, confirmation_code, email_address): |
68 | + self._fill_confirmation_form(confirmation_code, email_address) |
69 | + self._continue() |
70 | + return u1testutils.sso.sst.pages.CompleteEmailValidation() |
71 | + |
72 | + def _fill_confirmation_form(self, confirmation_code, email_address): |
73 | + sst.actions.write_textfield('id_confirmation_code', confirmation_code) |
74 | + sst.actions.write_textfield('id_email', email_address) |
75 | + |
76 | + def _continue(self): |
77 | + sst.actions.click_button(sst.actions.get_element(name='continue')) |
78 | + |
79 | + @log_action(logging.info) |
80 | + def confirm_with_error(self, confirmation_code, email_address): |
81 | + self._fill_confirmation_form(confirmation_code, email_address) |
82 | + self._continue() |
83 | + return self |
84 | + |
85 | + |
86 | +class DeleteEmail(u1testutils.sso.sst.pages.PageWithUserSubheader): |
87 | + |
88 | + title = 'Delete unverified email' |
89 | + url_path = '/+remove-email' |
90 | + |
91 | + @log_action(logging.info) |
92 | + def confirm(self): |
93 | + confirm_button = sst.actions.get_element(name='delete') |
94 | + sst.actions.click_button(confirm_button) |
95 | + user_name = self.subheader.get_user_name() |
96 | + return YourEmailAddresses(user_name) |
97 | + |
98 | + |
99 | +class ResetPassword(u1testutils.sso.sst.pages.PageWithAnonymousSubheader): |
100 | + |
101 | + title = 'Reset password' |
102 | + url_path = '/+forgot_password' |
103 | + headings1 = [ |
104 | + 'Ubuntu Single Sign On', |
105 | + 'Reset your Ubuntu Single Sign On password' |
106 | + ] |
107 | + |
108 | + @log_action(logging.info) |
109 | + def request_password_reset(self, email_address): |
110 | + sst.actions.write_textfield('id_email', email_address) |
111 | + # Even though the recaptcha field is ignored for our tests, we do |
112 | + # want to verify that it is on the page. |
113 | + sst.actions.write_textfield('recaptcha_response_field', 'ignored') |
114 | + sst.actions.click_button(sst.actions.get_element(name='continue')) |
115 | + |
116 | + |
117 | +class LogInFromRedirect(u1testutils.sso.sst.pages.LogIn): |
118 | + |
119 | + url_path = '/.*/\+decide' |
120 | + is_url_path_regex = True |
121 | + headings2 = ['Log in', 'Are you new?'] |
122 | |
123 | === modified file 'identityprovider/tests/acceptance/shared/helpers.py' |
124 | --- identityprovider/tests/acceptance/shared/helpers.py 2013-04-12 16:27:10 +0000 |
125 | +++ identityprovider/tests/acceptance/shared/helpers.py 2013-04-19 19:28:26 +0000 |
126 | @@ -1,15 +1,15 @@ |
127 | import re |
128 | from urllib import quote |
129 | |
130 | +import u1testutils.sso.sst.pages |
131 | + |
132 | from django.conf import settings |
133 | from sst.actions import ( |
134 | assert_checkbox_value, |
135 | assert_text_contains, |
136 | assert_title, |
137 | - assert_title_contains, |
138 | assert_url, |
139 | click_button, |
140 | - click_link, |
141 | exists_element, |
142 | get_base_url, |
143 | get_current_url, |
144 | @@ -19,13 +19,15 @@ |
145 | set_radio_value, |
146 | skip, |
147 | wait_for, |
148 | - write_textfield, |
149 | ) |
150 | from sst import config |
151 | - |
152 | from u1testutils import mail |
153 | -from u1testutils.sso import mail as sso_mail |
154 | +from u1testutils.sso import ( |
155 | + data, |
156 | + mail as sso_mail |
157 | +) |
158 | |
159 | +from identityprovider.tests.acceptance import pages |
160 | from identityprovider.tests.acceptance.shared import devices, urls |
161 | |
162 | |
163 | @@ -51,30 +53,34 @@ |
164 | email_address = mail.make_unique_test_email_address() |
165 | |
166 | vcode = None |
167 | - go_to(urls.NEW_ACCOUNT) |
168 | - wait_for(assert_title, 'Create account') |
169 | - fill_registration_form(email_address, displayname, password) |
170 | - click_button(get_element(name='continue')) |
171 | + |
172 | + create_account = u1testutils.sso.sst.pages.CreateAccount(open_page=True) |
173 | + |
174 | + user = data.User(displayname, email_address, password) |
175 | + create_account.create_ubuntu_sso_account(user) |
176 | |
177 | vcode = None |
178 | if 'allow_unverified' in config.flags: |
179 | - wait_for(assert_title_contains, "%s's details" % displayname) |
180 | + u1testutils.sso.sst.pages.YourAccount(user.full_name) |
181 | # default is not to verify for ALLOW_UNVERIFIED |
182 | if verify is None: |
183 | verify = False |
184 | if verify: |
185 | vlink = sso_mail.get_verification_link_for_address(email_address) |
186 | go_to(vlink) |
187 | - click_button(get_element(css_class='btn')) |
188 | + validate_email = \ |
189 | + u1testutils.sso.sst.pages.CompleteEmailValidation() |
190 | + validate_email.confirm() |
191 | else: |
192 | - wait_for(assert_title_contains, 'Account creation mail sent') |
193 | + mail_sent = u1testutils.sso.sst.pages.AccountCreationMailSent() |
194 | # old flow requries verify, usually |
195 | if verify is None: |
196 | verify = True |
197 | if verify: |
198 | vcode = sso_mail.get_verification_code_for_address(email_address) |
199 | - write_textfield(get_element(name='confirmation_code'), vcode) |
200 | - click_button(get_element(css_class='btn')) |
201 | + # TODO add the site not recognized parameter and use the right |
202 | + # public method. |
203 | + mail_sent._confirm_email(vcode) |
204 | |
205 | _LAST_EMAIL = email_address |
206 | _LAST_PASSWORD = password |
207 | @@ -83,34 +89,24 @@ |
208 | |
209 | |
210 | def fill_registration_form( |
211 | - email, |
212 | - displayname="My Name", |
213 | - password="Admin007", |
214 | - passwordconf=None): |
215 | + email, displayname="My Name", password="Admin007", passwordconf=None): |
216 | |
217 | - if passwordconf is None: |
218 | - passwordconf = password |
219 | - write_textfield('id_displayname', displayname) |
220 | - write_textfield('id_email', email) |
221 | - write_textfield('id_password', password) |
222 | - write_textfield('id_passwordconfirm', passwordconf) |
223 | - if exists_element(id='recaptcha_response_field'): |
224 | - write_textfield('recaptcha_response_field', 'ignored') |
225 | + user = data.User(displayname, email, password) |
226 | + create_account = u1testutils.sso.sst.pages.CreateAccount(open_page=True) |
227 | + # TODO we either make the fill public, or call a public higher method, |
228 | + # The latter sounds better. |
229 | + create_account._fill_new_account_form(user, passwordconf) |
230 | |
231 | |
232 | def add_email(address, verify=False): |
233 | - go_to(urls.EMAILS) |
234 | - wait_for(assert_title_contains, "'s email addresses") |
235 | - write_textfield('id_newemail', address) |
236 | - click_button(get_element(name='continue')) |
237 | + your_email_addresses = pages.YourEmailAddresses(open_page=True) |
238 | + your_email_addresses.add_email(address) |
239 | code = sso_mail.get_verification_code_for_address(address) |
240 | if verify: |
241 | - go_to(urls.ENTER_TOKEN) |
242 | - wait_for(write_textfield, 'id_confirmation_code', code) |
243 | - write_textfield('id_email', address) |
244 | - click_button(get_element(name='continue')) |
245 | - assert_title('Complete email address validation') |
246 | - click_button(get_element(name='continue')) |
247 | + enter_confirmation_code = pages.EnterConfirmationCode(open_page=True) |
248 | + complete_email_validation = enter_confirmation_code.confirm( |
249 | + code, address) |
250 | + complete_email_validation.confirm() |
251 | return code |
252 | |
253 | |
254 | @@ -154,21 +150,20 @@ |
255 | |
256 | |
257 | def delete_email(): |
258 | - go_to(urls.EMAILS) |
259 | - remove_link = get_element(tag='a', text='Delete') |
260 | - click_link(remove_link) |
261 | - confirm_button = get_element(name='delete') |
262 | - click_button(confirm_button) |
263 | + your_email_addresses = pages.YourEmailAddresses(open_page=True) |
264 | + delete_email_confirmation = your_email_addresses.delete_email() |
265 | + delete_email_confirmation.confirm() |
266 | |
267 | |
268 | def try_to_validate_email(address, code, finish_validation=True): |
269 | - go_to(urls.ENTER_TOKEN) |
270 | - wait_for(write_textfield, 'id_confirmation_code', code) |
271 | - write_textfield('id_email', address) |
272 | - click_button(get_element(name='continue')) |
273 | + # TODO implement the navigation and use the right public methods. |
274 | + enter_confirmation_code = pages.EnterConfirmationCode(open_page=True) |
275 | + enter_confirmation_code._fill_confirmation_form( |
276 | + code, address) |
277 | + enter_confirmation_code._continue() |
278 | if finish_validation: |
279 | - assert_title('Complete email address validation') |
280 | - click_button(get_element(name='continue')) |
281 | + complete = u1testutils.sso.sst.pages.CompleteEmailValidation() |
282 | + complete.confirm() |
283 | |
284 | |
285 | def login_or_register_account(device_cleanup=False): |
286 | @@ -190,10 +185,12 @@ |
287 | if email is None and password is None: |
288 | email = _LAST_EMAIL |
289 | password = _LAST_PASSWORD |
290 | - go_to(urls.HOME) |
291 | - write_textfield('id_email', email) |
292 | - write_textfield('id_password', password) |
293 | - click_button(get_element(name='continue')) |
294 | + log_in = u1testutils.sso.sst.pages.LogIn(open_page=True) |
295 | + # TODO we need the user name too. |
296 | + user = data.User('TODO', email, password) |
297 | + # TODO add the site not recognized parameter and use the right public |
298 | + # method. |
299 | + log_in._log_in(user) |
300 | |
301 | |
302 | def logout_and_in(): |
303 | @@ -206,17 +203,13 @@ |
304 | |
305 | |
306 | def logout(): |
307 | - go_to(urls.LOGOUT) |
308 | + u1testutils.sso.sst.pages.YouHaveBeenLoggedOut(open_page=True) |
309 | |
310 | |
311 | def request_password_reset(email_address): |
312 | logout() |
313 | - go_to(urls.FORGOT_PASSWORD) |
314 | - write_textfield('id_email', email_address) |
315 | - # Even though the recaptcha field is ignored for our tests, we do |
316 | - # want to verify that it is on the page. |
317 | - write_textfield('recaptcha_response_field', 'ignored') |
318 | - click_button(get_element(name='continue')) |
319 | + reset_password = pages.ResetPassword(open_page=True) |
320 | + reset_password.request_password_reset(email_address) |
321 | |
322 | |
323 | def login_to_test_account(): |
324 | @@ -254,12 +247,11 @@ |
325 | |
326 | def login_from_redirect(email=settings.QA_ACCOUNT_EMAIL, |
327 | password=settings.QA_ACCOUNT_PASSWORD): |
328 | - wait_for(assert_title, 'Log in') |
329 | - write_textfield('id_email', email) |
330 | - write_textfield('id_password', password) |
331 | - click_button(get_element(name='continue')) |
332 | - wait_for(assert_title_contains, 'Authenticate to') |
333 | - click_button(get_element(name='yes')) |
334 | + log_in = pages.LogInFromRedirect() |
335 | + # TODO we also need the user name. |
336 | + user = data.User('TODO', email, password) |
337 | + site_not_recognized = log_in.log_in_to_site_not_recognized(user) |
338 | + site_not_recognized.yes_sign_me_in() |
339 | |
340 | |
341 | def check_2f_for_url(url): |
342 | |
343 | === modified file 'requirements/testing.txt' |
344 | --- requirements/testing.txt 2013-04-12 21:17:08 +0000 |
345 | +++ requirements/testing.txt 2013-04-19 19:28:26 +0000 |
346 | @@ -28,6 +28,6 @@ |
347 | zope.interface==4.0.1 |
348 | zope.schema==4.2.0 |
349 | zope.testbrowser==3.5.1 |
350 | -bzr+http://bazaar.launchpad.net/~canonical-isd-qa/selenium-simple-test/trunk/@362 |
351 | -bzr+http://bazaar.launchpad.net/~canonical-isd-hackers/u1-test-utils/trunk@48 |
352 | +bzr+http://bazaar.launchpad.net/~canonical-isd-qa/selenium-simple-test/trunk/@376 |
353 | +bzr+http://bazaar.launchpad.net/~canonical-isd-hackers/u1-test-utils/trunk@53 |
354 | bzr+ssh://bazaar.launchpad.net/~bloodearnest/+junk/test-email-server/ |
355 | |
356 | === modified file 'scripts/acceptance-dev.sh' |
357 | --- scripts/acceptance-dev.sh 2013-04-09 12:35:33 +0000 |
358 | +++ scripts/acceptance-dev.sh 2013-04-19 19:28:26 +0000 |
359 | @@ -31,7 +31,7 @@ |
360 | sleep 10 # Time for the sso to start |
361 | |
362 | # run tests |
363 | -SST_BASE_URL="http://0.0.0.0:$PORT" fab acceptance:screenshot=true,report=xml,extended=true,flags="$SST_FLAGS" |
364 | +SST_BASE_URL="http://0.0.0.0:$PORT" fab acceptance:screenshot=true,report=xml,flags="$SST_FLAGS" |
365 | |
366 | # terminate sso server |
367 | screen -X -S sso quit |
368 | |
369 | === modified file 'scripts/run-acceptance-tests' |
370 | --- scripts/run-acceptance-tests 2013-04-08 20:43:46 +0000 |
371 | +++ scripts/run-acceptance-tests 2013-04-19 19:28:26 +0000 |
372 | @@ -51,5 +51,5 @@ |
373 | # dev is special: we need to start it up. |
374 | ./scripts/acceptance-dev.sh |
375 | else |
376 | - SST_BASE_URL="$SST_BASE_URL" fab acceptance:screenshot=true,report=xml,extended=true,flags="$SST_FLAGS" |
377 | + SST_BASE_URL="$SST_BASE_URL" fab acceptance:screenshot=true,report=xml,flags="$SST_FLAGS" |
378 | fi |
$ ./scripts/ run-acceptance- tests dev ------- ------- ------- ------- ------- ------- ------- ------- -------
[...]
-------
Ran 110 tests in 1628.942s
OK