Merge lp:~elopio/canonical-identity-provider/refactory_with_u1testutils-1 into lp:canonical-identity-provider/release

Proposed by Leo Arias
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
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.

To post a comment you must log in.
Revision history for this message
Leo Arias (elopio) wrote :

$ ./scripts/run-acceptance-tests dev
[...]
----------------------------------------------------------------------
Ran 110 tests in 1628.942s

OK

Revision history for this message
Leo Arias (elopio) wrote :

$ ./scripts/run-acceptance-tests dev
----------------------------------------------------------------------
Ran 110 tests in 1308.872s

OK

Save again :)

Revision history for this message
Leo Arias (elopio) wrote :
Revision history for this message
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?

review: Needs Fixing
Revision history for this message
Ricardo Kirkner (ricardokirkner) wrote :

l. 19-20, we could replace this with helpers.logout_and_in()

Revision history for this message
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.

Revision history for this message
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

Revision history for this message
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.

review: Approve
Revision history for this message
Ricardo Kirkner (ricardokirkner) wrote :

LGTM

review: Approve
Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
Download full text (69.5 KiB)

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/isd-download-cache
Using saved parent location: bzr+ssh://bazaar.launchpad.net/~canonical-isd-hackers/+junk/download-cache/
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.............................................................................................................................................................................................done.
Installing pip...............done.
[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-plpython-9.1 2> /dev/null | grep '^ii' | wc -l
[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-egenix-mx-base-dev 2> /dev/null | grep '^ii' | wc -l
[localhost] local: rm -rf M2Crypto*
[localhost] local: ln -s /usr/lib/python2.7/dist-packages/M2Crypto* .
[localhost] local: /usr/lib/config-manager/cm.py update /tmp/tmpqiWvt2
[localhost] local: . /mnt/tarmac/cache/canonical-identity-provider/.env/bin/activate && make install PACKAGES="-r /mnt/tarmac/cache/canonical-identity-provider/requirements.txt"
pip install --find-links=file:///mnt/tarmac/isd-download-cache --no-index pip==dev
Ignoring indexes: http://pypi.python.org/simple/
Downloading/unpacking pip==dev
  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/_build/_sources'
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/_build/_sources'
    Installing pip script to /mnt/tarmac/cache/canonical-identity-provider/.env/bin
    Installing pip-2.7 script to /mnt/tarmac/cache/canonical-identity-provider/.env/bin
Successfully installed pip
Cleaning up...
pip install --find-links=. --no-index -r /mnt/tarmac/cache/canonical-identity-provider/requirements.txt
Ignoring indexes: http://pypi.python.org...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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