Merge lp:~elopio/reminders-app/fix_with_account into lp:reminders-app

Proposed by Leo Arias
Status: Merged
Approved by: Nicholas Skaggs
Approved revision: 189
Merged at revision: 168
Proposed branch: lp:~elopio/reminders-app/fix_with_account
Merge into: lp:reminders-app
Prerequisite: lp:~nskaggs/reminders-app/fix-new-pep8
Diff against target: 424 lines (+197/-81)
4 files modified
tests/autopilot/reminders/credentials.py (+56/-14)
tests/autopilot/reminders/tests/__init__.py (+67/-58)
tests/autopilot/reminders/tests/test_credentials.py (+70/-0)
tests/autopilot/reminders/tests/test_reminders.py (+4/-9)
To merge this branch: bzr merge lp:~elopio/reminders-app/fix_with_account
Reviewer Review Type Date Requested Status
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
David Planella Approve
Nicholas Skaggs Pending
Review via email: mp+224539@code.launchpad.net

This proposal supersedes a proposal from 2014-06-23.

Commit message

Added logging messages and tests to the credentials autopilot tests helpers.

Description of the change

Added logging messages and tests to the credentials autopilot tests helpers.

To post a comment you must log in.
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Nicholas Skaggs (nskaggs) wrote : Posted in a previous version of this proposal

This still fails on the desktop for me.. no account created :-(

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Nicholas Skaggs (nskaggs) wrote : Posted in a previous version of this proposal

These greatly improves things, though still has some interesting behaviours that can be observed running the tests.

review: Approve
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
188. By Leo Arias

Reverted manifest.json change.

189. By Leo Arias

Fixed comments.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :

FAILED: Continuous integration, rev:189
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~elopio/reminders-app/fix_with_account/+merge/224539/+edit-commit-message

http://91.189.93.70:8080/job/reminders-app-ci/414/
Executed test runs:
    SUCCESS: http://91.189.93.70:8080/job/generic-mediumtests-utopic/652
        deb: http://91.189.93.70:8080/job/generic-mediumtests-utopic/652/artifact/work/output/*zip*/output.zip
    SUCCESS: http://91.189.93.70:8080/job/reminders-app-utopic-amd64-ci/109

Click here to trigger a rebuild:
http://91.189.93.70:8080/job/reminders-app-ci/414/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
David Planella (dpm) wrote :

Looks good to me and it passes tests, but I'd like to have some more context from either Leo or Nick before top-approving.

review: Approve
Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

dpm, at the moment everything passes, but the credentials tests behave oddly. It seems the isolation isn't working well. In addition, on the phone we are unable to isolate properly. If we do so the app fails to launch currently.

Revision history for this message
David Planella (dpm) wrote :

I've tested this on the emulator, having installed both plugin packages built from this branch [1].

First I tested it with running the app, and then simply starting Ubuntu System Settings and trying to add a regular Evernote account. So if I go to System Settings and choose the Evernote account, it then shows me the login page. After entering my credentials, it seems to work (Evernote asks me if I want to re-authorize the app to access this account). However, after hitting the button to re-authorize, it then hangs forever like this: http://i.imgur.com/TZi6P4u.png

This is the full debug output [2] of Online Accounts, but the most interesting part are the last few lines:

qml: Account created!
EvernoteConnection not set up completely. You need to set a hostname and a token. Cannot execute job. ( FetchUsernameJob )
Error fetching username: "Token or hostname not set."

The "Account created!" debug message I simply added it to the plugin's Main.qml file, so it's not in this branch. In any case, it seems that fetching the user name does not work for some reason, and that's presumably causing UOA to hang.

[1] https://launchpad.net/~dpm/+archive/ppa/+packages?field.name_filter=&field.status_filter=&field.series_filter=utopic
[2] http://pastebin.ubuntu.com/7706895/

Revision history for this message
David Planella (dpm) wrote :

Ah well... please ignore the comment, I pasted it into the wrong browser tab and thus into the wrong MP... at least it was for the right app!

Sorry for the noise.

Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

Landing this to keep things moving forward. The credentials weirdness will live on for now.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/autopilot/reminders/credentials.py'
2--- tests/autopilot/reminders/credentials.py 2014-06-25 23:31:11 +0000
3+++ tests/autopilot/reminders/credentials.py 2014-06-25 23:31:11 +0000
4@@ -14,12 +14,16 @@
5 # You should have received a copy of the GNU General Public License
6 # along with this program. If not, see <http://www.gnu.org/licenses/>.
7
8-
9+import logging
10+import time
11 import threading
12
13 from gi.repository import Accounts, GLib, Signon
14
15
16+logger = logging.getLogger(__name__)
17+
18+
19 class CredentialsException(Exception):
20
21 """Exception for credentials problems."""
22@@ -52,6 +56,7 @@
23 :param oauth_token: The oauth token of the account.
24
25 """
26+ logger.debug('Add an evernote account.')
27 self._start_main_loop()
28
29 account = self._create_account()
30@@ -65,11 +70,17 @@
31
32 self._join_main_loop()
33
34+ # XXX Sometimes, the account fails to be enabled. This sleep seems to
35+ # fix it but we haven't yet found the reason. --elopio - 2014-06-25
36+ time.sleep(10)
37 self._enable_evernote_service(account)
38
39+ logger.info('Created the account with id: {}.'.format(account.id))
40+ self._log_accounts_info()
41 return account
42
43 def _create_account(self):
44+ logger.debug('Creating the Evernote account.')
45 account = self._manager.create_account('evernote')
46 account.set_enabled(True)
47 account.store(self._on_account_created, None)
48@@ -77,8 +88,12 @@
49
50 def _on_account_created(self, account, error, _):
51 if error:
52- self.error = error
53- self._main_loop.quit()
54+ self._quit_main_loop_on_error(error, 'storing account')
55+
56+ def _quit_main_loop_on_error(self, error, step):
57+ logger.error('Error {}.'.format(step))
58+ self.error = error
59+ self._main_loop.quit()
60
61 def _get_identity_info(self, user_name, password):
62 info = Signon.IdentityInfo.new()
63@@ -90,9 +105,10 @@
64 def _set_credentials_id_to_account(
65 self, identity, id_, error, account_dict):
66 if error:
67- self.error = error
68- self._main_loop.quit()
69+ self._quit_main_loop_on_error(
70+ error, 'storing credentials with info')
71
72+ logger.debug('Setting credentials to account.')
73 account = account_dict.get('account')
74 oauth_token = account_dict.get('oauth_token')
75 account.set_variant('CredentialsId', GLib.Variant('u', id_))
76@@ -100,9 +116,10 @@
77
78 def _process_session(self, account, error, oauth_token):
79 if error:
80- self.error = error
81- self._main_loop.quit()
82+ self._quit_main_loop_on_error(
83+ error, 'setting credentials id to account')
84
85+ logger.debug('Processing session.')
86 account_service = Accounts.AccountService.new(account, None)
87 auth_data = account_service.get_auth_data()
88 identity = auth_data.get_credentials_id()
89@@ -119,15 +136,39 @@
90
91 def _on_login_processed(self, session, reply, error, userdata):
92 if error:
93- self.error = error
94+ self._quit_main_loop_on_error(error, 'processing session')
95
96- self._main_loop.quit()
97+ else:
98+ self._main_loop.quit()
99
100 def _enable_evernote_service(self, account):
101+ logger.debug('Enabling evernote service.')
102 service = self._manager.get_service('evernote')
103 account.select_service(service)
104 account.set_enabled(True)
105- account.store(self._on_account_created, None)
106+ account.store(self._on_service_enabled, None)
107+
108+ def _on_service_enabled(self, account, error, _):
109+ if error:
110+ self._quit_main_loop_on_error(error, 'enabling service')
111+
112+ def _log_accounts_info(self):
113+ account_ids = self._manager.list()
114+ logger.debug('Existing accounts: {}.'.format(account_ids))
115+ for id_ in account_ids:
116+ account = self._manager.get_account(id_)
117+ self._log_account_info(account)
118+
119+ def _log_account_info(self, account):
120+ logger.debug('Account info:')
121+ logger.debug('id: {}'.format(account.id))
122+ logger.debug('provider: {}'.format(account.get_provider_name()))
123+ logger.debug('enabled: {}'.format(account.get_enabled()))
124+ logger.debug('Account services:')
125+ for service in account.list_services():
126+ logger.debug('name: {}'.format(service.get_name()))
127+ account_service = Accounts.AccountService.new(account, service)
128+ logger.debug('enabled: {}'.format(account_service.get_enabled()))
129
130 def delete_account(self, account):
131 """Delete an account.
132@@ -135,13 +176,14 @@
133 :param account: The account to delete.
134
135 """
136+ logger.info('Deleting the account with id {}.'.format(account.id))
137 self._start_main_loop()
138 account.delete()
139 account.store(self._on_account_deleted, None)
140 self._join_main_loop()
141
142- def _on_account_deleted(self, account, error, userdata):
143+ def _on_account_deleted(self, account, error, _):
144 if error:
145- self.error = error
146-
147- self._main_loop.quit()
148+ self._quit_main_loop_on_error(error, 'deleting account')
149+ else:
150+ self._main_loop.quit()
151
152=== modified file 'tests/autopilot/reminders/tests/__init__.py'
153--- tests/autopilot/reminders/tests/__init__.py 2014-06-25 23:31:11 +0000
154+++ tests/autopilot/reminders/tests/__init__.py 2014-06-25 23:31:11 +0000
155@@ -16,14 +16,13 @@
156
157 """Reminders app autopilot tests."""
158
159+import logging
160 import os
161 import shutil
162-import logging
163+import subprocess
164
165 import fixtures
166 from autopilot import logging as autopilot_logging
167-from autopilot.input import Mouse, Touch, Pointer
168-from autopilot.platform import model
169 from autopilot.testcase import AutopilotTestCase
170 from ubuntuuitoolkit import (
171 emulators as toolkit_emulators,
172@@ -35,15 +34,13 @@
173 logger = logging.getLogger(__name__)
174
175
176-class RemindersAppTestCase(AutopilotTestCase):
177-
178- """A common test case class that provides several useful methods for
179- reminders-app tests."""
180-
181- if model() == 'Desktop':
182- scenarios = [('with mouse', dict(input_device_class=Mouse))]
183- else:
184- scenarios = [('with touch', dict(input_device_class=Touch))]
185+class BaseTestCaseWithTempHome(AutopilotTestCase):
186+
187+ """Base test case that patches the home directory.
188+
189+ That way we start the tests with a clean environment.
190+
191+ """
192
193 local_location = os.path.dirname(os.path.dirname(os.getcwd()))
194
195@@ -53,7 +50,20 @@
196 installed_location_binary = '/usr/bin/reminders'
197 installed_location_qml = '/usr/share/reminders/qml/reminders.qml'
198
199- def get_launcher_and_type(self):
200+ def setUp(self):
201+ self.kill_signond()
202+ self.addCleanup(self.kill_signond)
203+ super(BaseTestCaseWithTempHome, self).setUp()
204+ _, test_type = self.get_launcher_method_and_type()
205+ self.home_dir = self._patch_home(test_type)
206+
207+ def kill_signond(self):
208+ # We kill signond so it's restarted using the temporary HOME. Otherwise
209+ # it will remain running until it has 5 seconds of inactivity, keeping
210+ # reference to other directories.
211+ subprocess.call(['pkill', '-9', 'signond'])
212+
213+ def get_launcher_method_and_type(self):
214 if os.path.exists(self.local_location_binary):
215 launcher = self.launch_test_local
216 test_type = 'local'
217@@ -65,27 +75,34 @@
218 test_type = 'click'
219 return launcher, test_type
220
221- def setUp(self):
222- launcher, test_type = self.get_launcher_and_type()
223- self.home_dir = self._patch_home(test_type)
224- self.pointing_device = Pointer(self.input_device_class.create())
225- super(RemindersAppTestCase, self).setUp()
226-
227- self.app = reminders.RemindersApp(launcher())
228-
229- def _copy_xauthority_file(self, directory):
230- """ Copy .Xauthority file to directory, if it exists in /home
231- """
232- xauth = os.path.expanduser(os.path.join('~', '.Xauthority'))
233- if os.path.isfile(xauth):
234- logger.debug("Copying .Xauthority to " + directory)
235- shutil.copyfile(
236- os.path.expanduser(os.path.join('~', '.Xauthority')),
237- os.path.join(directory, '.Xauthority'))
238+ @autopilot_logging.log_action(logger.info)
239+ def launch_test_local(self):
240+ self.useFixture(fixtures.EnvironmentVariable(
241+ 'QML2_IMPORT_PATH',
242+ newvalue=os.path.join(self.local_location, 'src/plugin')))
243+ return self.launch_test_application(
244+ self.local_location_binary,
245+ '-q', self.local_location_qml,
246+ app_type='qt',
247+ emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase)
248+
249+ @autopilot_logging.log_action(logger.info)
250+ def launch_test_installed(self):
251+ return self.launch_test_application(
252+ self.installed_location_binary,
253+ '-q ' + self.installed_location_qml,
254+ '--desktop_file_hint=/usr/share/applications/'
255+ 'reminders.desktop',
256+ app_type='qt',
257+ emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase)
258+
259+ @autopilot_logging.log_action(logger.info)
260+ def launch_test_click(self):
261+ return self.launch_click_package(
262+ 'com.ubuntu.reminders',
263+ emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase)
264
265 def _patch_home(self, test_type):
266- """ mock /home for testing purposes to preserve user data
267- """
268 temp_dir_fixture = fixtures.TempDir()
269 self.useFixture(temp_dir_fixture)
270 temp_dir = temp_dir_fixture.path
271@@ -114,29 +131,21 @@
272
273 return temp_dir
274
275- @autopilot_logging.log_action(logger.info)
276- def launch_test_local(self):
277- self.useFixture(fixtures.EnvironmentVariable(
278- 'QML2_IMPORT_PATH',
279- newvalue=os.path.join(self.local_location, 'src/plugin')))
280- return self.launch_test_application(
281- self.local_location_binary,
282- '-q', self.local_location_qml,
283- app_type='qt',
284- emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase)
285-
286- @autopilot_logging.log_action(logger.info)
287- def launch_test_installed(self):
288- return self.launch_test_application(
289- self.installed_location_binary,
290- '-q ' + self.installed_location_qml,
291- '--desktop_file_hint=/usr/share/applications/'
292- 'reminders.desktop',
293- app_type='qt',
294- emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase)
295-
296- @autopilot_logging.log_action(logger.info)
297- def launch_test_click(self):
298- return self.launch_click_package(
299- 'com.ubuntu.reminders',
300- emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase)
301+ def _copy_xauthority_file(self, directory):
302+ """Copy .Xauthority file to directory, if it exists in /home."""
303+ xauth = os.path.expanduser(os.path.join('~', '.Xauthority'))
304+ if os.path.isfile(xauth):
305+ logger.debug("Copying .Xauthority to " + directory)
306+ shutil.copyfile(
307+ os.path.expanduser(os.path.join('~', '.Xauthority')),
308+ os.path.join(directory, '.Xauthority'))
309+
310+
311+class RemindersAppTestCase(BaseTestCaseWithTempHome):
312+
313+ """Base test case that launches the reminders-app."""
314+
315+ def setUp(self):
316+ super(RemindersAppTestCase, self).setUp()
317+ launcher_method, _ = self.get_launcher_method_and_type()
318+ self.app = reminders.RemindersApp(launcher_method())
319
320=== added file 'tests/autopilot/reminders/tests/test_credentials.py'
321--- tests/autopilot/reminders/tests/test_credentials.py 1970-01-01 00:00:00 +0000
322+++ tests/autopilot/reminders/tests/test_credentials.py 2014-06-25 23:31:11 +0000
323@@ -0,0 +1,70 @@
324+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
325+#
326+# Copyright (C) 2014 Canonical Ltd
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 version 3 as
330+# published by the Free Software Foundation.
331+#
332+# This program is distributed in the hope that it will be useful,
333+# but WITHOUT ANY WARRANTY; without even the implied warranty of
334+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
335+# GNU General Public License for more details.
336+#
337+# You should have received a copy of the GNU General Public License
338+# along with this program. If not, see <http://www.gnu.org/licenses/>.
339+
340+import logging
341+
342+from gi.repository import Accounts
343+from testtools.matchers import HasLength
344+
345+from reminders import credentials, evernote, tests
346+
347+
348+logger = logging.getLogger(__name__)
349+
350+
351+class EvernoteCredentialsTestCase(tests.BaseTestCaseWithTempHome):
352+
353+ def setUp(self):
354+ super(EvernoteCredentialsTestCase, self).setUp()
355+ self.account_manager = credentials.AccountManager()
356+
357+ def add_evernote_account(self):
358+ account = self.account_manager.add_evernote_account(
359+ 'dummy', 'dummy', evernote.TEST_OAUTH_TOKEN)
360+ self.addCleanup(self.delete_account_and_manager, account)
361+ return account
362+
363+ def delete_account_and_manager(self, account):
364+ if account.id in self.account_manager._manager.list():
365+ self.account_manager.delete_account(account)
366+ del self.account_manager._manager
367+ del self.account_manager
368+
369+ def test_add_evernote_account_must_enable_it(self):
370+ account = self.add_evernote_account()
371+
372+ self.assertTrue(account.get_enabled())
373+
374+ def test_add_evernote_account_must_set_provider(self):
375+ account = self.add_evernote_account()
376+
377+ self.assertEqual(account.get_provider_name(), 'evernote')
378+
379+ def test_add_evernote_account_must_enable_evernote_service(self):
380+ account = self.add_evernote_account()
381+ services = account.list_services()
382+
383+ self.assertThat(services, HasLength(1))
384+ self.assertEqual(services[0].get_name(), 'evernote')
385+ service = Accounts.AccountService.new(account, services[0])
386+ self.assertTrue(service.get_enabled())
387+
388+ def test_delete_evernote_account_must_remove_it(self):
389+ account = self.add_evernote_account()
390+ self.assertThat(self.account_manager._manager.list(), HasLength(1))
391+
392+ self.account_manager.delete_account(account)
393+ self.assertThat(self.account_manager._manager.list(), HasLength(0))
394
395=== modified file 'tests/autopilot/reminders/tests/test_reminders.py'
396--- tests/autopilot/reminders/tests/test_reminders.py 2014-06-25 23:31:11 +0000
397+++ tests/autopilot/reminders/tests/test_reminders.py 2014-06-25 23:31:11 +0000
398@@ -66,6 +66,7 @@
399 super(RemindersTestCaseWithAccount, self).setUp()
400 no_account_dialog = self.app.main_view.no_account_dialog
401 self.add_evernote_account()
402+ logger.info('Waiting for the Evernote account to be created.')
403 no_account_dialog.wait_until_destroyed()
404 self.evernote_client = evernote.SandboxEvernoteClient()
405
406@@ -93,15 +94,9 @@
407 notebooks_page.add_notebook(test_notebook_title)
408
409 last_notebook = notebooks_page.get_notebooks()[-1]
410- # TODO there's a bug with the last updated value: http://pad.lv/1318751
411- # so we can't check the full tuple. Uncomment this as soon as the bug
412- # is fixed. --elopio - 2014-05-12
413- # self.assertEqual(
414- # last_notebook,
415- # (test_notebook_title, 'Last edited today', 'Private', 0))
416- self.assertEqual(last_notebook[0], test_notebook_title)
417- self.assertEqual(last_notebook[2], 'Private')
418- self.assertEqual(last_notebook[3], 0)
419+ self.assertEqual(
420+ last_notebook,
421+ (test_notebook_title, 'Last edited today', 'Private', 0))
422
423 def test_add_notebook_must_create_it_in_server(self):
424 """Test that an added notebook will be created on the server."""

Subscribers

People subscribed via source and target branches