Merge lp:~canonical-platform-qa/sudoku-app/clean_tests1 into lp:sudoku-app
- clean_tests1
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Leo Arias |
Approved revision: | 242 |
Merged at revision: | 244 |
Proposed branch: | lp:~canonical-platform-qa/sudoku-app/clean_tests1 |
Merge into: | lp:sudoku-app |
Diff against target: |
1085 lines (+492/-211) 7 files modified
sudoku-app.qml (+8/-4) tests/autopilot/sudoku_app/__init__.py (+56/-48) tests/autopilot/sudoku_app/pages/__init__.py (+21/-0) tests/autopilot/sudoku_app/pages/_settings_page.py (+235/-0) tests/autopilot/sudoku_app/tests/__init__.py (+36/-20) tests/autopilot/sudoku_app/tests/settings/test_profiles.py (+72/-0) tests/autopilot/sudoku_app/tests/test_sudoku.py (+64/-139) |
To merge this branch: | bzr merge lp:~canonical-platform-qa/sudoku-app/clean_tests1 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Nicholas Skaggs (community) | Approve | ||
Chris Gagnon (community) | Needs Fixing | ||
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Review via email: mp+228236@code.launchpad.net |
Commit message
Refactor autopilot tests for profiles.
Description of the change
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:240
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:240
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Chris Gagnon (chris.gagnon) wrote : | # |
The closing ) should be on it's own line if you want to stay compliant with the autopilot project coding format.
other than that it looks good to me
Nicholas Skaggs (nskaggs) wrote : | # |
Though I won't hold the MP for it, you really should propogate using the emulators import as we've deprecated it for the helpers.
emulators as toolkit_emulators,
I will disagree with Chris on the closing ); I really hate hanging )'s. The other thing of note is the backup and restore db, but that too can be another MP. test_new_
Overall, a major improvement.
Leo Arias (elopio) wrote : | # |
> The closing ) should be on it's own line if you want to stay compliant with
> the autopilot project coding format.
>
>
> other than that it looks good to me
Done. However, I think that for these projects we should stick to enforce things that are automatically checked by flake8.
We need a clear direction anyway, so lets talk about it during a stand up.
Leo Arias (elopio) wrote : | # |
> Though I won't hold the MP for it, you really should propogate using the
> emulators import as we've deprecated it for the helpers.
>
> emulators as toolkit_emulators,
>
>
> I will disagree with Chris on the closing ); I really hate hanging )'s. The
> other thing of note is the backup and restore db, but that too can be another
> MP. test_new_
> the test_settings (theme, difficulty, etc).
>
> Overall, a major improvement.
Yes, it's already to big to also remove the remaining toolkit_emulators. I made the change on the files that I already have to touch extensively.
All the remaining tests also need to be cleaned, and some need to be downgraded to qml tests. But that goes to the todo as time permits.
Thanks to both for the review. I'll top-approve now.
Preview Diff
1 | === modified file 'sudoku-app.qml' |
2 | --- sudoku-app.qml 2014-07-23 03:15:57 +0000 |
3 | +++ sudoku-app.qml 2014-07-29 23:33:54 +0000 |
4 | @@ -746,7 +746,7 @@ |
5 | } |
6 | } |
7 | } |
8 | - ToolbarButton { |
9 | + ToolbarButton { |
10 | action: Action { |
11 | objectName: "hintbutton" |
12 | id: revealHintAction |
13 | @@ -895,6 +895,8 @@ |
14 | property alias themeIndex: themeSelector.selectedIndex; |
15 | |
16 | page: Page { |
17 | + objectName: "settingsPage" |
18 | + |
19 | anchors { |
20 | left: parent.left |
21 | right: parent.right |
22 | @@ -906,15 +908,15 @@ |
23 | Component { |
24 | id: profileSelector |
25 | Dialog { |
26 | + objectName: "selectProfileDialog" |
27 | title: i18n.tr("Select profile") |
28 | |
29 | - |
30 | - |
31 | Column{ |
32 | height: mainColumnSettings.height*2/3 |
33 | ListView { |
34 | |
35 | id: profileListView |
36 | + objectName: "profileListView" |
37 | clip: true |
38 | width: parent.width |
39 | height: parent.height - units.gu(12) |
40 | @@ -935,7 +937,6 @@ |
41 | } |
42 | |
43 | SudokuDialogButton{ |
44 | - |
45 | anchors.horizontalCenter: parent.horizontalCenter |
46 | id:cancelButton |
47 | buttonText: i18n.tr("Cancel") |
48 | @@ -956,12 +957,14 @@ |
49 | Component { |
50 | id: manageProfileSelector |
51 | Dialog { |
52 | + objectName: "manageProfileDialog" |
53 | title: i18n.tr("Select profile") |
54 | |
55 | Column{ |
56 | height: mainColumnSettings.height*2/3 |
57 | ListView { |
58 | id: manageProfileListView |
59 | + objectName: "manageProfileListView" |
60 | clip: true |
61 | width: parent.width |
62 | height: parent.height - units.gu(12) |
63 | @@ -988,6 +991,7 @@ |
64 | |
65 | anchors.horizontalCenter: parent.horizontalCenter |
66 | id:cancelButton |
67 | + objectName: "cancelButton" |
68 | buttonText: i18n.tr("Cancel") |
69 | width: parent.width/2; |
70 | size: units.gu(5) |
71 | |
72 | === removed file 'tests/autopilot/sudoku_app/__init__.py' |
73 | --- tests/autopilot/sudoku_app/__init__.py 2013-07-11 16:46:16 +0000 |
74 | +++ tests/autopilot/sudoku_app/__init__.py 1970-01-01 00:00:00 +0000 |
75 | @@ -1,6 +0,0 @@ |
76 | -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
77 | -# Copyright 2013 Canonical |
78 | -# |
79 | -# This program is free software: you can redistribute it and/or modify it |
80 | -# under the terms of the GNU General Public License version 3, as published |
81 | -# by the Free Software Foundation. |
82 | |
83 | === renamed file 'tests/autopilot/sudoku_app/emulators.py' => 'tests/autopilot/sudoku_app/__init__.py' |
84 | --- tests/autopilot/sudoku_app/emulators.py 2014-05-15 13:04:32 +0000 |
85 | +++ tests/autopilot/sudoku_app/__init__.py 2014-07-29 23:33:54 +0000 |
86 | @@ -1,17 +1,51 @@ |
87 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
88 | -# Copyright 2013 Canonical |
89 | +# Copyright 2013, 2014 Canonical |
90 | # |
91 | -# This program is free software: you can redistribute it and/or modify it |
92 | -# under the terms of the GNU General Public License version 3, as published |
93 | +# This program is free software; you can redistribute it and/or modify |
94 | +# it under the terms of the GNU General Public License version 3, as published |
95 | # by the Free Software Foundation. |
96 | +# |
97 | +# This program is distributed in the hope that it will be useful, |
98 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
99 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
100 | +# GNU General Public License for more details. |
101 | +# |
102 | +# You should have received a copy of the GNU General Public License |
103 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
104 | |
105 | """Sudoku app autopilot emulators.""" |
106 | |
107 | -from ubuntuuitoolkit import emulators as toolkit_emulators |
108 | -import ubuntuuitoolkit._custom_proxy_objects |
109 | - |
110 | - |
111 | -class MainView(toolkit_emulators.MainView): |
112 | +import logging |
113 | + |
114 | +import autopilot.logging |
115 | +import ubuntuuitoolkit |
116 | +from autopilot import introspection |
117 | + |
118 | +# Not directly used because of the way autopilot loads custom proxy objects. |
119 | +from sudoku_app import pages |
120 | +pages |
121 | + |
122 | + |
123 | +logger = logging.getLogger(__name__) |
124 | + |
125 | + |
126 | +class SudokuApp: |
127 | + |
128 | + """Autopilot helper for the Sudoku application.""" |
129 | + |
130 | + def __init__(self, app_proxy): |
131 | + self.app_proxy = app_proxy |
132 | + self.main_view = self.app_proxy.select_single(MainView) |
133 | + |
134 | + |
135 | +class MainView(ubuntuuitoolkit.MainView): |
136 | + |
137 | + @autopilot.logging.log_action(logger.info) |
138 | + def go_to_settings(self): |
139 | + self.switch_to_tab('settingsTab') |
140 | + settings_page = self.select_single(objectName='settingsPage') |
141 | + settings_page.visible.wait_for(True) |
142 | + return settings_page |
143 | |
144 | def get_blank_inputs(self): |
145 | # generate a list of blank input fields from the game board |
146 | @@ -28,7 +62,7 @@ |
147 | return button |
148 | |
149 | def get_number_dialog(self): |
150 | - return self.wait_select_single("Dialog", objectName="picknumberscreen") |
151 | + return self.wait_select_single(objectName='picknumberscreen') |
152 | |
153 | def get_hints_switch(self): |
154 | return self.select_single("CheckBox", objectName="hintsSwitch") |
155 | @@ -51,45 +85,6 @@ |
156 | return self.wait_select_single(ubuntuuitoolkit.ToolbarButton, |
157 | objectName="hintbutton") |
158 | |
159 | - def get_current_profile(self): |
160 | - return self.select_single("SingleValue", objectName="Current profile") |
161 | - |
162 | - def get_sudoku_user_profile(self): |
163 | - return self.select_single("Standard", text="Sudoku User") |
164 | - |
165 | - def get_user_profile_cancel_button(self): |
166 | - return self.select_single("Button", objectName="profileCancelButton") |
167 | - |
168 | - def get_add_profile(self): |
169 | - return self.select_single("SingleValue", objectName="Add profile") |
170 | - |
171 | - def get_add_profile_dialog(self): |
172 | - return self.wait_select_single("Dialog", objectName="Add new profile") |
173 | - |
174 | - def get_add_profile_Lastname_field(self): |
175 | - return self.select_single("TextField", objectName="Lastname") |
176 | - |
177 | - def get_add_profile_Firstname_field(self): |
178 | - return self.select_single("TextField", objectName="Firstname") |
179 | - |
180 | - def get_add_profile_OKbutton(self): |
181 | - return self.select_single("SudokuDialogButton", objectName="OKbutton") |
182 | - |
183 | - def get_manage_profiles(self): |
184 | - return self.wait_select_single( |
185 | - "SingleValue", objectName="Manage profiles") |
186 | - |
187 | - def firstname_Mylastname_profile(self): |
188 | - return self.wait_select_single( |
189 | - "Standard", text="Myfirstname Mylastname") |
190 | - |
191 | - def get_edit_profile_dialog(self): |
192 | - return self.select_single("Dialog", objectName="Edit profile") |
193 | - |
194 | - def get_edit_profile_delete_button(self): |
195 | - return self.select_single("SudokuDialogButton", |
196 | - objectName="deleteButton") |
197 | - |
198 | def get_new_game_easy_button(self): |
199 | return self.wait_select_single("NewGameSelectionButton", |
200 | objectName="easyGameButton") |
201 | @@ -109,3 +104,16 @@ |
202 | def get_new_game_button(self, objectName): |
203 | return self.wait_select_single("NewGameSelectionButton", |
204 | objectName=objectName) |
205 | + |
206 | + |
207 | +class PickNumberDialog(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase): |
208 | + |
209 | + """Autopilot helper for the Add new profile dialog.""" |
210 | + |
211 | + @classmethod |
212 | + def validate_dbus_object(cls, path, state): |
213 | + name = introspection.get_classname_from_path(path) |
214 | + if name == b'Dialog': |
215 | + if state['objectName'][1] == 'picknumberscreen': |
216 | + return True |
217 | + return False |
218 | |
219 | === added directory 'tests/autopilot/sudoku_app/pages' |
220 | === added file 'tests/autopilot/sudoku_app/pages/__init__.py' |
221 | --- tests/autopilot/sudoku_app/pages/__init__.py 1970-01-01 00:00:00 +0000 |
222 | +++ tests/autopilot/sudoku_app/pages/__init__.py 2014-07-29 23:33:54 +0000 |
223 | @@ -0,0 +1,21 @@ |
224 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
225 | +# Copyright 2014 Canonical |
226 | +# |
227 | +# This program is free software; you can redistribute it and/or modify |
228 | +# it under the terms of the GNU General Public License version 3, as published |
229 | +# by the Free Software Foundation. |
230 | +# |
231 | +# This program is distributed in the hope that it will be useful, |
232 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
233 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
234 | +# GNU General Public License for more details. |
235 | +# |
236 | +# You should have received a copy of the GNU General Public License |
237 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
238 | + |
239 | +__all__ = [ |
240 | + 'SettingsPage' |
241 | +] |
242 | + |
243 | + |
244 | +from sudoku_app.pages._settings_page import SettingsPage |
245 | |
246 | === added file 'tests/autopilot/sudoku_app/pages/_settings_page.py' |
247 | --- tests/autopilot/sudoku_app/pages/_settings_page.py 1970-01-01 00:00:00 +0000 |
248 | +++ tests/autopilot/sudoku_app/pages/_settings_page.py 2014-07-29 23:33:54 +0000 |
249 | @@ -0,0 +1,235 @@ |
250 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
251 | +# Copyright 2014 Canonical |
252 | +# |
253 | +# This program is free software; you can redistribute it and/or modify |
254 | +# it under the terms of the GNU General Public License version 3, as published |
255 | +# by the Free Software Foundation. |
256 | +# |
257 | +# This program is distributed in the hope that it will be useful, |
258 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
259 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
260 | +# GNU General Public License for more details. |
261 | +# |
262 | +# You should have received a copy of the GNU General Public License |
263 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
264 | + |
265 | +import logging |
266 | + |
267 | +import autopilot.logging |
268 | +import ubuntuuitoolkit |
269 | +from autopilot import introspection |
270 | + |
271 | + |
272 | +logger = logging.getLogger(__name__) |
273 | + |
274 | + |
275 | +class SettingsPage(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase): |
276 | + |
277 | + """Autopilot helper for the Settings page.""" |
278 | + |
279 | + @classmethod |
280 | + def validate_dbus_object(cls, path, state): |
281 | + name = introspection.get_classname_from_path(path) |
282 | + if name == b'Page10': |
283 | + if state['objectName'][1] == 'settingsPage': |
284 | + return True |
285 | + return False |
286 | + |
287 | + @autopilot.logging.log_action(logger.info) |
288 | + def add_profile(self, last_name, first_name): |
289 | + self._click_item('Add profile') |
290 | + dialog = self.get_root_instance().select_single( |
291 | + objectName='Add new profile' |
292 | + ) |
293 | + dialog.add_new_profile(last_name, first_name) |
294 | + |
295 | + @autopilot.logging.log_action(logger.debug) |
296 | + def _click_item(self, object_name): |
297 | + item = self.select_single(objectName=object_name) |
298 | + flickable = self.select_single( |
299 | + ubuntuuitoolkit.QQuickFlickable, |
300 | + objectName='settingsContainer' |
301 | + ) |
302 | + flickable.swipe_child_into_view(item) |
303 | + self.pointing_device.click_object(item) |
304 | + |
305 | + def get_profiles(self): |
306 | + """Return a list with the names of the existing profiles.""" |
307 | + manage_profile_dialog = self._go_to_manage_profiles() |
308 | + profiles = manage_profile_dialog.get_profiles() |
309 | + manage_profile_dialog.click_cancel() |
310 | + return profiles |
311 | + |
312 | + @autopilot.logging.log_action(logger.debug) |
313 | + def _go_to_manage_profiles(self): |
314 | + self._click_item('Manage profiles') |
315 | + return self.get_root_instance().select_single( |
316 | + objectName='manageProfileDialog' |
317 | + ) |
318 | + |
319 | + @autopilot.logging.log_action(logger.debug) |
320 | + def change_profile(self, profile_name): |
321 | + select_profile_dialog = self._go_to_select_profiles() |
322 | + select_profile_dialog.select(profile_name) |
323 | + |
324 | + @autopilot.logging.log_action(logger.debug) |
325 | + def _go_to_select_profiles(self): |
326 | + self._click_item('Current profile') |
327 | + return self.get_root_instance().select_single( |
328 | + objectName='selectProfileDialog' |
329 | + ) |
330 | + |
331 | + def get_current_profile(self): |
332 | + """Return the name of the current profile.""" |
333 | + current_profile_item = self.select_single(objectName='Current profile') |
334 | + return current_profile_item.value |
335 | + |
336 | + @autopilot.logging.log_action(logger.info) |
337 | + def delete_profile(self, profile_name): |
338 | + manage_profile_dialog = self._go_to_manage_profiles() |
339 | + manage_profile_dialog.delete_profile(profile_name) |
340 | + |
341 | + |
342 | +class AddNewProfileDialog( |
343 | + ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase): |
344 | + |
345 | + """Autopilot helper for the Add new profile dialog.""" |
346 | + |
347 | + @classmethod |
348 | + def validate_dbus_object(cls, path, state): |
349 | + name = introspection.get_classname_from_path(path) |
350 | + if name == b'Dialog': |
351 | + if state['objectName'][1] == 'Add new profile': |
352 | + return True |
353 | + return False |
354 | + |
355 | + @autopilot.logging.log_action(logger.debug) |
356 | + def add_new_profile(self, last_name, first_name): |
357 | + self._fill_form(last_name, first_name) |
358 | + self._click_ok() |
359 | + self.wait_until_destroyed() |
360 | + |
361 | + @autopilot.logging.log_action(logger.debug) |
362 | + def _fill_form(self, last_name, first_name): |
363 | + last_name_text_field = self.select_single( |
364 | + ubuntuuitoolkit.TextField, |
365 | + objectName='Lastname' |
366 | + ) |
367 | + last_name_text_field.write(last_name) |
368 | + first_name_text_field = self.select_single( |
369 | + ubuntuuitoolkit.TextField, |
370 | + objectName='Firstname' |
371 | + ) |
372 | + first_name_text_field.write(first_name) |
373 | + |
374 | + def _click_ok(self): |
375 | + ok_button = self.select_single( |
376 | + 'SudokuDialogButton', |
377 | + objectName='OKbutton' |
378 | + ) |
379 | + self.pointing_device.click_object(ok_button) |
380 | + |
381 | + |
382 | +class ProfileDialog(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase): |
383 | + |
384 | + PROFILE_LIST_VIEW_OBJECT_NAME = None |
385 | + |
386 | + def get_profiles(self): |
387 | + """Return a list with the names of the existing profiles.""" |
388 | + profile_list_view = self._get_profile_list_view() |
389 | + profile_items = profile_list_view.select_many( |
390 | + ubuntuuitoolkit.listitems.Standard |
391 | + ) |
392 | + # Sort by the position on the list. |
393 | + sorted_items = sorted( |
394 | + profile_items, |
395 | + key=lambda item: item.globalRect.y) |
396 | + profiles = [item.text for item in sorted_items] |
397 | + return profiles |
398 | + |
399 | + def _get_profile_list_view(self): |
400 | + return self.select_single( |
401 | + ubuntuuitoolkit.QQuickListView, |
402 | + objectName=self.PROFILE_LIST_VIEW_OBJECT_NAME |
403 | + ) |
404 | + |
405 | + @autopilot.logging.log_action(logger.debug) |
406 | + def click_profile(self, profile_name): |
407 | + profile_list_view = self._get_profile_list_view() |
408 | + profile_item = profile_list_view.select_single( |
409 | + ubuntuuitoolkit.listitems.Standard, |
410 | + text=profile_name |
411 | + ) |
412 | + self.pointing_device.click_object(profile_item) |
413 | + |
414 | + |
415 | +class SelectProfileDialog(ProfileDialog): |
416 | + |
417 | + """Autopilot helper for the Select profile dialog.""" |
418 | + |
419 | + PROFILE_LIST_VIEW_OBJECT_NAME = 'profileListView' |
420 | + |
421 | + @classmethod |
422 | + def validate_dbus_object(cls, path, state): |
423 | + name = introspection.get_classname_from_path(path) |
424 | + if name == b'Dialog': |
425 | + if state['objectName'][1] == 'selectProfileDialog': |
426 | + return True |
427 | + return False |
428 | + |
429 | + def select(self, profile_name): |
430 | + self.click_profile(profile_name) |
431 | + self.wait_until_destroyed() |
432 | + |
433 | + |
434 | +class ManageProfileDialog(ProfileDialog): |
435 | + |
436 | + """Autopilot helper for the Select profile dialog.""" |
437 | + |
438 | + PROFILE_LIST_VIEW_OBJECT_NAME = 'manageProfileListView' |
439 | + |
440 | + @classmethod |
441 | + def validate_dbus_object(cls, path, state): |
442 | + name = introspection.get_classname_from_path(path) |
443 | + if name == b'Dialog': |
444 | + if state['objectName'][1] == 'manageProfileDialog': |
445 | + return True |
446 | + return False |
447 | + |
448 | + @autopilot.logging.log_action(logger.debug) |
449 | + def click_cancel(self): |
450 | + cancel_button = self.select_single( |
451 | + 'SudokuDialogButton', |
452 | + objectName='cancelButton' |
453 | + ) |
454 | + self.pointing_device.click_object(cancel_button) |
455 | + self.wait_until_destroyed() |
456 | + |
457 | + def delete_profile(self, profile_name): |
458 | + root = self.get_root_instance() |
459 | + self._open_profile(profile_name) |
460 | + self.wait_until_destroyed() |
461 | + edit_profile_dialog = root.select_single(objectName='Edit profile') |
462 | + edit_profile_dialog.delete() |
463 | + |
464 | + @autopilot.logging.log_action(logger.debug) |
465 | + def _open_profile(self, profile_name): |
466 | + self.click_profile(profile_name) |
467 | + |
468 | + |
469 | +class EditProfileDialog(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase): |
470 | + |
471 | + @classmethod |
472 | + def validate_dbus_object(cls, path, state): |
473 | + name = introspection.get_classname_from_path(path) |
474 | + if name == b'Dialog': |
475 | + if state['objectName'][1] == 'Edit profile': |
476 | + return True |
477 | + return False |
478 | + |
479 | + @autopilot.logging.log_action(logger.debug) |
480 | + def delete(self): |
481 | + delete_button = self.select_single( |
482 | + 'SudokuDialogButton', objectName='deleteButton') |
483 | + self.pointing_device.click_object(delete_button) |
484 | + self.wait_until_destroyed() |
485 | |
486 | === modified file 'tests/autopilot/sudoku_app/tests/__init__.py' |
487 | --- tests/autopilot/sudoku_app/tests/__init__.py 2014-07-02 13:52:53 +0000 |
488 | +++ tests/autopilot/sudoku_app/tests/__init__.py 2014-07-29 23:33:54 +0000 |
489 | @@ -1,9 +1,17 @@ |
490 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
491 | -# Copyright 2013 Canonical |
492 | +# Copyright 2013, 2014 Canonical |
493 | # |
494 | -# This program is free software: you can redistribute it and/or modify it |
495 | -# under the terms of the GNU General Public License version 3, as published |
496 | +# This program is free software; you can redistribute it and/or modify |
497 | +# it under the terms of the GNU General Public License version 3, as published |
498 | # by the Free Software Foundation. |
499 | +# |
500 | +# This program is distributed in the hope that it will be useful, |
501 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
502 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
503 | +# GNU General Public License for more details. |
504 | +# |
505 | +# You should have received a copy of the GNU General Public License |
506 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
507 | |
508 | """Sudoku app autopilot tests.""" |
509 | |
510 | @@ -12,14 +20,16 @@ |
511 | import logging |
512 | |
513 | from autopilot.input import Mouse, Touch, Pointer |
514 | +from autopilot.matchers import Eventually |
515 | from autopilot.platform import model |
516 | from autopilot.testcase import AutopilotTestCase |
517 | - |
518 | +from testtools.matchers import Equals |
519 | from ubuntuuitoolkit import ( |
520 | base, |
521 | emulators as toolkit_emulators, |
522 | ) |
523 | -from sudoku_app import emulators |
524 | + |
525 | +import sudoku_app |
526 | |
527 | logger = logging.getLogger(__name__) |
528 | |
529 | @@ -49,31 +59,40 @@ |
530 | self.addCleanup(self.restore_sqlite_db) |
531 | |
532 | if os.path.exists(self.local_location): |
533 | - self.launch_test_local() |
534 | + app_proxy = self.launch_test_local() |
535 | elif os.path.exists('/usr/share/sudoku-app/sudoku-app.qml'): |
536 | - self.launch_test_installed() |
537 | + app_proxy = self.launch_test_installed() |
538 | else: |
539 | - self.launch_test_click() |
540 | + app_proxy = self.launch_test_click() |
541 | + |
542 | + self.app = sudoku_app.SudokuApp(app_proxy) |
543 | + self.assertThat( |
544 | + self.app.main_view.visible, |
545 | + Eventually(Equals(True)) |
546 | + ) |
547 | |
548 | def launch_test_local(self): |
549 | - self.app = self.launch_test_application( |
550 | + return self.launch_test_application( |
551 | base.get_qmlscene_launch_command(), |
552 | self.local_location, |
553 | app_type='qt', |
554 | - emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase) |
555 | + emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase |
556 | + ) |
557 | |
558 | def launch_test_installed(self): |
559 | - self.app = self.launch_test_application( |
560 | + return self.launch_test_application( |
561 | base.get_qmlscene_launch_command(), |
562 | "/usr/share/sudoku-app/sudoku-app.qml", |
563 | "--desktop_file_hint=/usr/share/applications/sudoku-app.desktop", |
564 | app_type='qt', |
565 | - emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase) |
566 | + emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase |
567 | + ) |
568 | |
569 | def launch_test_click(self): |
570 | - self.app = self.launch_click_package( |
571 | + return self.launch_click_package( |
572 | 'com.ubuntu.sudoku', |
573 | - emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase) |
574 | + emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase |
575 | + ) |
576 | |
577 | def temp_move_sqlite_db(self): |
578 | try: |
579 | @@ -96,14 +115,11 @@ |
580 | try: |
581 | shutil.rmtree(self.sqlite_dir) |
582 | except: |
583 | - logger.error("Failed to remove test database and restore" / |
584 | - "database") |
585 | + logger.error( |
586 | + 'Failed to remove test database and restore database' |
587 | + ) |
588 | return |
589 | try: |
590 | shutil.move(self.backup_dir, self.sqlite_dir) |
591 | except: |
592 | logger.error("Failed to restore database") |
593 | - |
594 | - @property |
595 | - def main_view(self): |
596 | - return self.app.select_single(emulators.MainView) |
597 | |
598 | === added directory 'tests/autopilot/sudoku_app/tests/settings' |
599 | === added file 'tests/autopilot/sudoku_app/tests/settings/__init__.py' |
600 | === added file 'tests/autopilot/sudoku_app/tests/settings/test_profiles.py' |
601 | --- tests/autopilot/sudoku_app/tests/settings/test_profiles.py 1970-01-01 00:00:00 +0000 |
602 | +++ tests/autopilot/sudoku_app/tests/settings/test_profiles.py 2014-07-29 23:33:54 +0000 |
603 | @@ -0,0 +1,72 @@ |
604 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
605 | +# Copyright 2013, 2014 Canonical |
606 | +# |
607 | +# This program is free software; you can redistribute it and/or modify |
608 | +# it under the terms of the GNU General Public License version 3, as published |
609 | +# by the Free Software Foundation. |
610 | +# |
611 | +# This program is distributed in the hope that it will be useful, |
612 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
613 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
614 | +# GNU General Public License for more details. |
615 | +# |
616 | +# You should have received a copy of the GNU General Public License |
617 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
618 | + |
619 | +import uuid |
620 | + |
621 | +from sudoku_app import tests |
622 | + |
623 | + |
624 | +class ProfilesTestCase(tests.SudokuTestCase): |
625 | + |
626 | + def setUp(self): |
627 | + super().setUp() |
628 | + self.settings_page = self.app.main_view.go_to_settings() |
629 | + |
630 | + def add_new_test_profile(self): |
631 | + # There is no need to delete the profile created because we are using a |
632 | + # clean database. |
633 | + unique_id = uuid.uuid1() |
634 | + test_last_name = 'Test last name {}'.format(unique_id) |
635 | + test_first_name = 'Test first name {}'.format(unique_id) |
636 | + |
637 | + self.settings_page.add_profile(test_last_name, test_first_name) |
638 | + |
639 | + return test_first_name, test_last_name |
640 | + |
641 | + def format_profile_name(self, first_name, last_name): |
642 | + return '{} {}'.format(first_name, last_name) |
643 | + |
644 | + def test_add_new_profile_must_make_it_available_in_manage_profiles(self): |
645 | + test_first_name, test_last_name = self.add_new_test_profile() |
646 | + |
647 | + profiles = self.settings_page.get_profiles() |
648 | + self.assertIn( |
649 | + self.format_profile_name(test_first_name, test_last_name), |
650 | + profiles |
651 | + ) |
652 | + |
653 | + def test_change_profile_must_update_selected_profile(self): |
654 | + test_first_name, test_last_name = self.add_new_test_profile() |
655 | + formated_test_profile_name = self.format_profile_name( |
656 | + test_first_name, test_last_name |
657 | + ) |
658 | + |
659 | + self.settings_page.change_profile(formated_test_profile_name) |
660 | + |
661 | + self.assertEqual( |
662 | + self.settings_page.get_current_profile(), |
663 | + formated_test_profile_name |
664 | + ) |
665 | + |
666 | + def test_delete_profile_must_remove_it_from_manage_profiles(self): |
667 | + test_first_name, test_last_name = self.add_new_test_profile() |
668 | + formated_test_profile_name = self.format_profile_name( |
669 | + test_first_name, test_last_name |
670 | + ) |
671 | + |
672 | + self.settings_page.delete_profile(formated_test_profile_name) |
673 | + |
674 | + profiles = self.settings_page.get_profiles() |
675 | + self.assertNotIn(formated_test_profile_name, profiles) |
676 | |
677 | === modified file 'tests/autopilot/sudoku_app/tests/test_sudoku.py' |
678 | --- tests/autopilot/sudoku_app/tests/test_sudoku.py 2014-07-02 13:52:53 +0000 |
679 | +++ tests/autopilot/sudoku_app/tests/test_sudoku.py 2014-07-29 23:33:54 +0000 |
680 | @@ -1,9 +1,17 @@ |
681 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
682 | -# Copyright 2013 Canonical |
683 | +# Copyright 2013, 2014 Canonical |
684 | # |
685 | -# This program is free software: you can redistribute it and/or modify it |
686 | -# under the terms of the GNU General Public License version 3, as published |
687 | +# This program is free software; you can redistribute it and/or modify |
688 | +# it under the terms of the GNU General Public License version 3, as published |
689 | # by the Free Software Foundation. |
690 | +# |
691 | +# This program is distributed in the hope that it will be useful, |
692 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
693 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
694 | +# GNU General Public License for more details. |
695 | +# |
696 | +# You should have received a copy of the GNU General Public License |
697 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
698 | |
699 | """Sudoku app autopilot tests.""" |
700 | |
701 | @@ -15,18 +23,13 @@ |
702 | |
703 | class TestMainWindow(SudokuTestCase): |
704 | |
705 | - def setUp(self): |
706 | - super(TestMainWindow, self).setUp() |
707 | - self.assertThat( |
708 | - self.main_view.visible, Eventually(Equals(True))) |
709 | - |
710 | def test_enter_and_clear_number(self): |
711 | # find the first button that has a blank value |
712 | - gridButtons = self.main_view.get_blank_inputs() |
713 | + gridButtons = self.app.main_view.get_blank_inputs() |
714 | gridButton = gridButtons[0] |
715 | |
716 | # create a value function to check later using id |
717 | - buttonValue = lambda: self.main_view.select_single( |
718 | + buttonValue = lambda: self.app.main_view.select_single( |
719 | "QQuickText", id=gridButton.id).text |
720 | |
721 | # double check that it's blank |
722 | @@ -36,10 +39,10 @@ |
723 | self.pointing_device.click_object(gridButton) |
724 | |
725 | # assert that we can see the input screen |
726 | - self.main_view.get_number_dialog() |
727 | + self.app.main_view.get_number_dialog() |
728 | |
729 | # set a value, choose 4 |
730 | - dialogButton = self.main_view.get_dialog_button("4") |
731 | + dialogButton = self.app.main_view.get_dialog_button("4") |
732 | self.pointing_device.click_object(dialogButton) |
733 | |
734 | # check the value to ensure it worked |
735 | @@ -49,10 +52,10 @@ |
736 | self.pointing_device.click_object(gridButton) |
737 | |
738 | # make sure we can see the input screen |
739 | - self.main_view.get_number_dialog() |
740 | + self.app.main_view.get_number_dialog() |
741 | |
742 | # set a value, choose clear |
743 | - dialogButton = self.main_view.get_dialog_button("Clear") |
744 | + dialogButton = self.app.main_view.get_dialog_button("Clear") |
745 | self.pointing_device.click_object(dialogButton) |
746 | |
747 | # check the value to ensure it worked |
748 | @@ -60,24 +63,25 @@ |
749 | |
750 | def test_best_scores_tab(self): |
751 | # switch to best scores tab |
752 | - self.main_view.switch_to_tab("highscoresTab") |
753 | + self.app.main_view.switch_to_tab("highscoresTab") |
754 | |
755 | # make sure we are in the right place |
756 | - self.main_view.wait_select_single("Tab", objectName="highscoresTab") |
757 | + self.app.main_view.wait_select_single( |
758 | + "Tab", objectName="highscoresTab") |
759 | |
760 | # click current user button |
761 | - header = self.main_view.get_header() |
762 | + header = self.app.main_view.get_header() |
763 | header.click_action_button('currentuserbutton') |
764 | |
765 | # check label |
766 | - label = lambda: self.main_view.wait_select_single( |
767 | + label = lambda: self.app.main_view.wait_select_single( |
768 | "Header", objectName="highscoreslabel").text |
769 | self.assertThat( |
770 | label, |
771 | Eventually(NotEquals("<b>Best scores for all players</b>"))) |
772 | |
773 | # click all users button |
774 | - header = self.main_view.get_header() |
775 | + header = self.app.main_view.get_header() |
776 | header.click_action_button('allusersbutton') |
777 | |
778 | # check label again |
779 | @@ -87,11 +91,11 @@ |
780 | |
781 | def test_enter_and_cancel(self): |
782 | # find the first button that has a blank value |
783 | - gridButtons = self.main_view.get_blank_inputs() |
784 | + gridButtons = self.app.main_view.get_blank_inputs() |
785 | gridButton = gridButtons[0] |
786 | |
787 | # create a value function to check later using id |
788 | - buttonValue = lambda: self.main_view.select_single( |
789 | + buttonValue = lambda: self.app.main_view.select_single( |
790 | "QQuickText", id=gridButton.id).text |
791 | |
792 | # double check that it's blank |
793 | @@ -101,10 +105,10 @@ |
794 | self.pointing_device.click_object(gridButton) |
795 | |
796 | # make that we can see the input screen |
797 | - self.main_view.get_number_dialog() |
798 | + self.app.main_view.get_number_dialog() |
799 | |
800 | # set a value, choose 4 |
801 | - dialogButton = self.main_view.get_dialog_button("4") |
802 | + dialogButton = self.app.main_view.get_dialog_button("4") |
803 | self.pointing_device.click_object(dialogButton) |
804 | |
805 | # check the value to ensure it worked |
806 | @@ -114,10 +118,10 @@ |
807 | self.pointing_device.click_object(gridButton) |
808 | |
809 | # make sure that we can see the input screen |
810 | - self.main_view.get_number_dialog() |
811 | + self.app.main_view.get_number_dialog() |
812 | |
813 | # set a value, choose clear |
814 | - dialogButton = self.main_view.get_dialog_button("Cancel") |
815 | + dialogButton = self.app.main_view.get_dialog_button("Cancel") |
816 | self.pointing_device.click_object(dialogButton) |
817 | |
818 | # check the value to ensure it worked |
819 | @@ -145,75 +149,75 @@ |
820 | |
821 | def test_about_tab(self): |
822 | # Switch to the 'About' tab |
823 | - self.main_view.switch_to_tab("aboutTab") |
824 | + self.app.main_view.switch_to_tab("aboutTab") |
825 | |
826 | # Check image loads |
827 | - aboutImage = lambda: self.main_view.select_single( |
828 | + aboutImage = lambda: self.app.main_view.select_single( |
829 | "QQuickImage", objectName="aboutImage").progress |
830 | self.assertThat(aboutImage, Eventually(Equals(1.0))) |
831 | |
832 | # Check the 'Author(s):' label is displayed |
833 | - aboutLabel = lambda: self.main_view.select_single( |
834 | + aboutLabel = lambda: self.app.main_view.select_single( |
835 | "Label", objectName="authorLabel").text |
836 | self.assertThat(aboutLabel, Eventually(Equals("Author(s): "))) |
837 | |
838 | # Check the 'Contact:' label is displayed |
839 | - contactLabel = lambda: self.main_view.select_single( |
840 | + contactLabel = lambda: self.app.main_view.select_single( |
841 | "Label", objectName="contactLabel").text |
842 | self.assertThat(contactLabel, Eventually(Equals("Contact: "))) |
843 | |
844 | # Check correct Launchpad URL: is displayed |
845 | - urlLabel = lambda: self.main_view.select_single( |
846 | + urlLabel = lambda: self.app.main_view.select_single( |
847 | "Label", objectName="urlLabel").text |
848 | self.assertThat(urlLabel, Eventually(Equals( |
849 | '<a href="https://launchpad.net/sudoku-app">' |
850 | 'https://launchpad.net/sudoku-app</a>'))) |
851 | |
852 | # Check the 'Version:' label is displayed |
853 | - versionLabel = lambda: self.main_view.select_single( |
854 | + versionLabel = lambda: self.app.main_view.select_single( |
855 | "Label", objectName="versionLabel").text |
856 | self.assertThat(versionLabel, Eventually(Equals("Version: "))) |
857 | |
858 | # Check correct version is displayed |
859 | - version = lambda: self.main_view.select_single( |
860 | + version = lambda: self.app.main_view.select_single( |
861 | "Label", objectName="version").text |
862 | self.assertThat(version, Eventually(Equals("1.5"))) |
863 | |
864 | # Check correct year is displayed |
865 | - yearLabel = lambda: self.main_view.select_single( |
866 | + yearLabel = lambda: self.app.main_view.select_single( |
867 | "Label", objectName="yearLabel").text |
868 | self.assertThat(yearLabel, Eventually(Equals("2013"))) |
869 | |
870 | def test_hint_button(self): |
871 | # open settings tab |
872 | - self.main_view.switch_to_tab("settingsTab") |
873 | + self.app.main_view.switch_to_tab("settingsTab") |
874 | |
875 | # click on hints switch to enable hints toolbar button |
876 | - hintsSwitchClickable = self.main_view.get_hints_switchClickable() |
877 | + hintsSwitchClickable = self.app.main_view.get_hints_switchClickable() |
878 | |
879 | self.pointing_device.click_object(hintsSwitchClickable) |
880 | |
881 | # verify hints switch is clicked |
882 | - self.assertThat(self.main_view.get_hints_switch().checked, |
883 | + self.assertThat(self.app.main_view.get_hints_switch().checked, |
884 | Eventually(Equals(True))) |
885 | |
886 | # exit settings tab by clicking on sudoku tab |
887 | - self.main_view.switch_to_tab("MainTab") |
888 | + self.app.main_view.switch_to_tab("MainTab") |
889 | |
890 | # click on hint button on toolbar |
891 | - header = self.main_view.get_header() |
892 | + header = self.app.main_view.get_header() |
893 | header.click_action_button('hintbutton') |
894 | |
895 | - number_of_hints = lambda: self.main_view.select_single( |
896 | + number_of_hints = lambda: self.app.main_view.select_single( |
897 | objectName="blockgrid").numberOfHints |
898 | self.assertThat(number_of_hints, Eventually(Equals(1))) |
899 | |
900 | def test_theme_change(self): |
901 | # open settings tab |
902 | - self.main_view.switch_to_tab("settingsTab") |
903 | + self.app.main_view.switch_to_tab("settingsTab") |
904 | |
905 | # ******** check theme selector ******** |
906 | - themeSelector = self.main_view.get_theme_selector() |
907 | + themeSelector = self.app.main_view.get_theme_selector() |
908 | |
909 | # select UbuntuColours option |
910 | themeSelector.select_option('Label', text='UbuntuColours') |
911 | @@ -238,10 +242,10 @@ |
912 | |
913 | def test_difficulty_selector(self): |
914 | # open settings tab |
915 | - self.main_view.switch_to_tab("settingsTab") |
916 | + self.app.main_view.switch_to_tab("settingsTab") |
917 | |
918 | # ******** check difficulty selector ******** |
919 | - difficulty = self.main_view.get_difficulty_selector() |
920 | + difficulty = self.app.main_view.get_difficulty_selector() |
921 | |
922 | # select Easy |
923 | difficulty.select_option('Label', text='Easy') |
924 | @@ -280,104 +284,24 @@ |
925 | |
926 | def test_hint_switch(self): |
927 | # open settings tab |
928 | - self.main_view.switch_to_tab("settingsTab") |
929 | + self.app.main_view.switch_to_tab("settingsTab") |
930 | |
931 | # ******** check hint switch ******** |
932 | # select hints switch |
933 | - hintsSwitchClickable = self.main_view.get_hints_switchClickable() |
934 | + hintsSwitchClickable = self.app.main_view.get_hints_switchClickable() |
935 | self.assertThat(hintsSwitchClickable.text, Eventually(Equals("Hints"))) |
936 | - hintsSwitch = self.main_view.get_hints_switch() |
937 | + hintsSwitch = self.app.main_view.get_hints_switch() |
938 | |
939 | # switch it on or off depending on it's state |
940 | self.pointing_device.click_object(hintsSwitchClickable) |
941 | self.assertThat(hintsSwitch.checked, Eventually(Equals(True))) |
942 | |
943 | - def test_profiles(self): |
944 | - # open settings tab |
945 | - self.main_view.switch_to_tab("settingsTab") |
946 | - |
947 | - # ******** check profile settings ******** |
948 | - # select current profile |
949 | - currentProfile = self.main_view.get_current_profile() |
950 | - self.pointing_device.click_object(currentProfile) |
951 | - |
952 | - # let's change profile |
953 | - # select "sudoku user" profile |
954 | - sudokuUserProfile = self.main_view.get_sudoku_user_profile() |
955 | - self.pointing_device.click_object(sudokuUserProfile) |
956 | - |
957 | - # verify changed profile |
958 | - currentProfile = self.main_view.get_current_profile() |
959 | - self.assertThat(currentProfile.value, Equals("Sudoku User")) |
960 | - |
961 | - # let's add a user profile |
962 | - # verify add profile page opens |
963 | - sudokuAddProfile = self.main_view.get_add_profile() |
964 | - self.pointing_device.click_object(sudokuAddProfile) |
965 | - |
966 | - sudokuAddProfileDialog = self.main_view.get_add_profile_dialog() |
967 | - |
968 | - # insert Lastname |
969 | - lastName = self.main_view.get_add_profile_Lastname_field() |
970 | - self.pointing_device.click_object(lastName) |
971 | - self.assertThat(lastName.placeholderText, |
972 | - Eventually(Equals("Lastname"))) |
973 | - self.keyboard.type("Mylastname") |
974 | - self.assertThat(lastName.text, Eventually(Equals("Mylastname"))) |
975 | - |
976 | - # insert Firstname |
977 | - firstName = self.main_view.get_add_profile_Firstname_field() |
978 | - self.pointing_device.click_object(firstName) |
979 | - self.assertThat(firstName.placeholderText, |
980 | - Eventually(Equals("Firstname"))) |
981 | - self.keyboard.type("Myfirstname") |
982 | - self.assertThat(firstName.text, Eventually(Equals("Myfirstname"))) |
983 | - |
984 | - # click OK button |
985 | - OKButton = self.main_view.get_add_profile_OKbutton() |
986 | - self.assertThat(OKButton.buttonText, Eventually(Equals("OK"))) |
987 | - self.pointing_device.click_object(OKButton) |
988 | - sudokuAddProfileDialog.wait_until_destroyed() |
989 | - |
990 | - # ******** check manage profiles ******** |
991 | - # select manage profile |
992 | - x, y, _, _ = self.main_view.globalRect |
993 | - line_x = x + self.main_view.width * 0.50 |
994 | - start_y = y + self.main_view.height * 0.75 |
995 | - stop_y = y + self.main_view.height * 0.6 |
996 | - |
997 | - self.pointing_device.drag(line_x, start_y, line_x, stop_y) |
998 | - self._wait_to_stop_moving() |
999 | - |
1000 | - manageProfile = self.main_view.get_manage_profiles() |
1001 | - self.pointing_device.click_object(manageProfile) |
1002 | - |
1003 | - # click on the new profile just added |
1004 | - myProfile = self.main_view.wait_select_single( |
1005 | - "Standard", |
1006 | - text="Myfirstname Mylastname") |
1007 | - self.assertThat(myProfile.text, |
1008 | - Eventually(Equals("Myfirstname Mylastname"))) |
1009 | - self.pointing_device.click_object(myProfile) |
1010 | - |
1011 | - # click on delete |
1012 | - deleteButton = self.main_view.get_edit_profile_delete_button() |
1013 | - self.assertThat(deleteButton.buttonText, Eventually(Equals("Delete"))) |
1014 | - self.pointing_device.click_object(deleteButton) |
1015 | - |
1016 | - # check and make sure the profile is gone |
1017 | - |
1018 | - def _wait_to_stop_moving(self): |
1019 | - self.main_view.select_single( |
1020 | - 'QQuickFlickable', |
1021 | - objectName='settingsContainer').moving.wait_for(False) |
1022 | - |
1023 | def _set_difficulty(self, selection, label): |
1024 | # open settings tab |
1025 | - self.main_view.switch_to_tab("settingsTab") |
1026 | + self.app.main_view.switch_to_tab("settingsTab") |
1027 | |
1028 | # set the difficulty of the game |
1029 | - difficulty = self.main_view.get_difficulty_selector() |
1030 | + difficulty = self.app.main_view.get_difficulty_selector() |
1031 | |
1032 | # select Easy |
1033 | difficulty.select_option('Label', text=label) |
1034 | @@ -388,39 +312,40 @@ |
1035 | |
1036 | def _verify_game_start(self, askmode=False, button=None): |
1037 | # check the game starts properly (according to difficulty) |
1038 | - self.main_view.switch_to_tab("MainTab") |
1039 | - header = self.main_view.get_header() |
1040 | + self.app.main_view.switch_to_tab("MainTab") |
1041 | + header = self.app.main_view.get_header() |
1042 | header.click_action_button('newgamebutton') |
1043 | |
1044 | # if we're in ask mode, make sure we can grab all the buttons |
1045 | # and click the proper button |
1046 | if askmode: |
1047 | self.assertThat( |
1048 | - self.main_view.get_new_game_easy_button().buttonText, |
1049 | + self.app.main_view.get_new_game_easy_button().buttonText, |
1050 | Eventually(Equals("Easy"))) |
1051 | self.assertThat( |
1052 | - self.main_view.get_new_game_moderate_button().buttonText, |
1053 | + self.app.main_view.get_new_game_moderate_button().buttonText, |
1054 | Eventually(Equals("Moderate"))) |
1055 | self.assertThat( |
1056 | - self.main_view.get_new_game_hard_button().buttonText, |
1057 | + self.app.main_view.get_new_game_hard_button().buttonText, |
1058 | Eventually(Equals("Hard"))) |
1059 | self.assertThat( |
1060 | - self.main_view.get_new_game_ultrahard_button().buttonText, |
1061 | + self.app.main_view.get_new_game_ultrahard_button().buttonText, |
1062 | Eventually(Equals("Ultra\nHard"))) |
1063 | self.pointing_device.click_object( |
1064 | - self.main_view.get_new_game_button(button)) |
1065 | + self.app.main_view.get_new_game_button(button)) |
1066 | |
1067 | - number_of_hints = lambda: self.main_view.select_single( |
1068 | + number_of_hints = lambda: self.app.main_view.select_single( |
1069 | objectName="blockgrid").numberOfHints |
1070 | - number_of_actions = lambda: self.main_view.select_single( |
1071 | + number_of_actions = lambda: self.app.main_view.select_single( |
1072 | objectName="blockgrid").numberOfActions |
1073 | |
1074 | self.assertThat(number_of_hints, Eventually(Equals(0))) |
1075 | self.assertThat(number_of_actions, Eventually(Equals(0))) |
1076 | |
1077 | # verify clock is moving |
1078 | - game_seconds = self.main_view.select_single( |
1079 | + game_seconds = self.app.main_view.select_single( |
1080 | objectName="blockgrid").gameSeconds |
1081 | self.assertThat( |
1082 | - self.main_view.select_single(objectName="blockgrid").gameSeconds, |
1083 | + self.app.main_view.select_single( |
1084 | + objectName="blockgrid").gameSeconds, |
1085 | Eventually(NotEquals(game_seconds))) |
FAILED: Continuous integration, rev:239 91.189. 93.70:8080/ job/sudoku- app-ci/ 108/ 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 1137/console 91.189. 93.70:8080/ job/sudoku- app-utopic- amd64-ci/ 18/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/sudoku- app-ci/ 108/rebuild
http://