Merge lp:~elopio/ubuntu-rssreader-app/refactor_tests into lp:~ubuntu-shorts-dev/ubuntu-rssreader-app/trunk
- refactor_tests
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Nicholas Skaggs |
Approved revision: | 186 |
Merged at revision: | 187 |
Proposed branch: | lp:~elopio/ubuntu-rssreader-app/refactor_tests |
Merge into: | lp:~ubuntu-shorts-dev/ubuntu-rssreader-app/trunk |
Diff against target: |
414 lines (+169/-131) 3 files modified
feeds/AppendFeedPage.qml (+17/-1) tests/autopilot/shorts_app/emulators.py (+95/-6) tests/autopilot/shorts_app/tests/test_rssreader.py (+57/-124) |
To merge this branch: | bzr merge lp:~elopio/ubuntu-rssreader-app/refactor_tests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chris Gagnon (community) | Approve | ||
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Carla Sella (community) | Approve | ||
Leo Arias | Pending | ||
Review via email: mp+208517@code.launchpad.net |
Commit message
Cleaned a test to add a feed to a new topic.
Description of the change
I started refactoring the first test, but it includes an add and delete test. This branch only includes the add part. So, for now I'm not removing any old code or tests. I find it nicer to go slowly.
Please let me know what you think, and if we should continue writing the tests this way.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
Chris Gagnon (chris.gagnon) wrote : | # |
I'd really like to see a local http started to serve rss files from 127.0.0.1 instead of an external website.
there is an example here you can re-use to serve an rss xml file.
https:/
Carla Sella (carla-sella) wrote : | # |
I think that writing tests this way is fine.
Carla Sella (carla-sella) : | # |
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:185
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: 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:186
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Chris Gagnon (chris.gagnon) wrote : | # |
We should really mock the network calls, without looking too closely it looks like google provides a library to do this. https:/
I won't hold up this MP for not mocking the network, but it should be on the roadmap for autopilot tests in this project.
Preview Diff
1 | === modified file 'feeds/AppendFeedPage.qml' |
2 | --- feeds/AppendFeedPage.qml 2014-01-15 16:27:41 +0000 |
3 | +++ feeds/AppendFeedPage.qml 2014-03-04 04:12:43 +0000 |
4 | @@ -1,3 +1,19 @@ |
5 | +/* |
6 | + * Copyright (C) 2013, 2014 |
7 | + * |
8 | + * This program is free software; you can redistribute it and/or modify |
9 | + * it under the terms of the GNU General Public License as published by |
10 | + * the Free Software Foundation; version 3. |
11 | + * |
12 | + * This program is distributed in the hope that it will be useful, |
13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | + * GNU General Public License for more details. |
16 | + * |
17 | + * You should have received a copy of the GNU General Public License |
18 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | + */ |
20 | + |
21 | import QtQuick 2.0 |
22 | import QtQuick.XmlListModel 2.0 |
23 | import Ubuntu.Components 0.1 |
24 | @@ -249,7 +265,7 @@ |
25 | |
26 | delegate: ListItem.Standard { |
27 | text: model.title |
28 | - objectName: "feedpagelistitem" |
29 | + objectName: "feedpagelistitem-" + model.title |
30 | |
31 | control: CheckBox { |
32 | anchors.verticalCenter: parent.verticalCenter |
33 | |
34 | === modified file 'tests/autopilot/shorts_app/emulators.py' |
35 | --- tests/autopilot/shorts_app/emulators.py 2014-01-15 16:27:41 +0000 |
36 | +++ tests/autopilot/shorts_app/emulators.py 2014-03-04 04:12:43 +0000 |
37 | @@ -1,6 +1,6 @@ |
38 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
39 | # |
40 | -# Copyright (C) 2013 Canonical Ltd. |
41 | +# Copyright (C) 2013, 2014 Canonical Ltd. |
42 | # |
43 | # This program is free software; you can redistribute it and/or modify |
44 | # it under the terms of the GNU Lesser General Public License as published by |
45 | @@ -14,14 +14,41 @@ |
46 | # You should have received a copy of the GNU Lesser General Public License |
47 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
48 | |
49 | +import logging |
50 | +from time import sleep |
51 | + |
52 | +from autopilot import logging as autopilot_logging |
53 | +from testtools.matchers import NotEquals |
54 | from ubuntuuitoolkit import emulators as toolkit_emulators |
55 | -from time import sleep |
56 | + |
57 | + |
58 | +logger = logging.getLogger(__name__) |
59 | |
60 | |
61 | class MainView(toolkit_emulators.MainView): |
62 | |
63 | retry_delay = 0.2 |
64 | |
65 | + @autopilot_logging.log_action(logger.info) |
66 | + def go_to_add_feeds(self): |
67 | + popover = self._click_add_reads() |
68 | + popover.click_button_by_text('+ Add feeds') |
69 | + return self.select_single( |
70 | + AppendFeedPage, objectName='appendfeedpage') |
71 | + |
72 | + def _click_add_reads(self): |
73 | + toolbar = self.open_toolbar() |
74 | + toolbar.click_button('addreadsbutton') |
75 | + return self.get_action_selection_popover('addreadspopover') |
76 | + |
77 | + def get_selected_tab_title(self): |
78 | + tabs = self.get_tabs() |
79 | + selected_tab_index = tabs.selectedTabIndex |
80 | + # TODO there are other tabs that are not of TopicTab type. |
81 | + # --elopio - 2014-02-26 |
82 | + tab = tabs.select_single('TopicTab', index=selected_tab_index) |
83 | + return tab.title |
84 | + |
85 | #ideally this should be converted to the sdk |
86 | #and use object name not text names |
87 | #see https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1205144 |
88 | @@ -83,10 +110,6 @@ |
89 | #grab just the first checkbox |
90 | return self.select_many_retry("CheckBox", objectName="feedCheckbox")[0] |
91 | |
92 | - def get_append_page_list_items(self): |
93 | - return self.select_many_retry("Standard", |
94 | - objectName="feedpagelistitem") |
95 | - |
96 | def get_next_button(self): |
97 | return self.select_single("Button", objectName="nextButton") |
98 | |
99 | @@ -200,3 +223,69 @@ |
100 | def get_editfeed_valueselector_value(self, name): |
101 | valueselector = self.get_editfeed_topic_valueselector() |
102 | return valueselector.select_single("LabelVisual", text=name) |
103 | + |
104 | + |
105 | +class Page(toolkit_emulators.MainView): |
106 | + """Autopilot helper for the Page objects.""" |
107 | + |
108 | + def __init__(self, *args): |
109 | + super(Page, self).__init__(*args) |
110 | + # XXX we need a better way to keep reference to the main view. |
111 | + # --elopio - 2014-02-26 |
112 | + self.main_view = self.get_root_instance().select_single(MainView) |
113 | + |
114 | + @autopilot_logging.log_action(logger.info) |
115 | + def click_next(self): |
116 | + toolbar = self.main_view.get_toolbar() |
117 | + next_button = toolbar.select_single('Button', objectName='nextButton') |
118 | + self.pointing_device.click_object(next_button) |
119 | + |
120 | + |
121 | +class AppendFeedPage(Page): |
122 | + """Autopilot helper for the Append Feed page.""" |
123 | + |
124 | + @autopilot_logging.log_action(logger.info) |
125 | + def search_feed(self, keyword_or_url): |
126 | + search_text_field = self.select_single( |
127 | + toolkit_emulators.TextField, objectName='tfFeedUrl') |
128 | + # Write and press enter. |
129 | + search_text_field.write(keyword_or_url + '\n') |
130 | + self._wait_for_results_to_appear() |
131 | + |
132 | + def _wait_for_results_to_appear(self): |
133 | + results_list = self._get_results_list() |
134 | + results_list.count.wait_for(NotEquals(0)) |
135 | + |
136 | + def _get_results_list(self): |
137 | + return self.select_single( |
138 | + toolkit_emulators.QQuickListView, objectName='feedpagelistview') |
139 | + |
140 | + @autopilot_logging.log_action(logger.info) |
141 | + def select_results(self, *results): |
142 | + """Select feed items from the list of results. |
143 | + |
144 | + :param results: The titles of the items to select from the list. |
145 | + |
146 | + """ |
147 | + for result in results: |
148 | + self._check_result(result) |
149 | + |
150 | + def click_next(self): |
151 | + super(AppendFeedPage, self).click_next() |
152 | + return self.main_view.select_single( |
153 | + ChooseTopicPage, objectName='choosetopicpage') |
154 | + |
155 | + def _check_result(self, result): |
156 | + results_list = self._get_results_list() |
157 | + results_list.click_element('feedpagelistitem-{}'.format(result)) |
158 | + |
159 | + |
160 | +class ChooseTopicPage(Page): |
161 | + """Autopilot helper for the Choose Topic Page page.""" |
162 | + |
163 | + @autopilot_logging.log_action(logger.info) |
164 | + def add_topic(self, topic): |
165 | + new_topic_text_field = self.select_single( |
166 | + toolkit_emulators.TextField, objectName='newTopic') |
167 | + # Write and press enter. |
168 | + new_topic_text_field.write(topic + '\n') |
169 | |
170 | === modified file 'tests/autopilot/shorts_app/tests/test_rssreader.py' |
171 | --- tests/autopilot/shorts_app/tests/test_rssreader.py 2014-02-13 03:52:29 +0000 |
172 | +++ tests/autopilot/shorts_app/tests/test_rssreader.py 2014-03-04 04:12:43 +0000 |
173 | @@ -1,9 +1,18 @@ |
174 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
175 | -# Copyright 2013 Canonical |
176 | -# |
177 | -# This program is free software: you can redistribute it and/or modify it |
178 | -# under the terms of the GNU General Public License version 3, as published |
179 | -# by the Free Software Foundation. |
180 | +# |
181 | +# Copyright (C) 2013, 2014 Canonical Ltd. |
182 | +# |
183 | +# This program is free software; you can redistribute it and/or modify |
184 | +# it under the terms of the GNU Lesser General Public License as published by |
185 | +# the Free Software Foundation; version 3. |
186 | +# |
187 | +# This program is distributed in the hope that it will be useful, |
188 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
189 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
190 | +# GNU Lesser General Public License for more details. |
191 | +# |
192 | +# You should have received a copy of the GNU Lesser General Public License |
193 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
194 | |
195 | """shorts app autopilot tests.""" |
196 | |
197 | @@ -42,79 +51,28 @@ |
198 | self.main_view.get_network_activity, |
199 | Eventually(Equals(None), timeout=60)) |
200 | |
201 | - def _add_feed_and_topic(self, feed, topicName): |
202 | - """test add feed and topic""" |
203 | - logger.debug("starting test add feed and topic") |
204 | - |
205 | - self.assertThat(self.main_view.get_topics_page, |
206 | - Eventually(NotEquals(None))) |
207 | - #open toolbar |
208 | - logger.debug("opening toolbar") |
209 | - toolbar = self.main_view.open_toolbar() |
210 | - |
211 | - #click on add reads toolbar button |
212 | - logger.debug("clicking addreadsbutton") |
213 | - toolbar.click_button("addreadsbutton") |
214 | - |
215 | - #click on add feeds popover action |
216 | - logger.debug("clicking + Add feeds") |
217 | - addReadsPopover = self.main_view.get_action_popover() |
218 | - self.main_view.run_action(addReadsPopover, "+ Add feeds") |
219 | - |
220 | - #verify Append Feed page is open |
221 | - logger.debug("asserting append page") |
222 | - appendpage = lambda: self.main_view.get_append_page().visible |
223 | - self.assertThat(appendpage, Eventually(Equals(True))) |
224 | - |
225 | - #type feed in input field |
226 | - logger.debug("inputting feed") |
227 | - self._input_new_feed(feed) |
228 | - |
229 | - #click on checkbox to confirm feed |
230 | - logger.debug("asserting checkbox") |
231 | - self.assertThat(self.main_view.get_append_page_feed, |
232 | - Eventually(Not(Is(None)))) |
233 | - logger.debug("grabbing checkbox") |
234 | - checkboxBtn = self.main_view.get_append_page_feed() |
235 | - logger.debug("clicking checkbox") |
236 | - self.pointing_device.click_object(checkboxBtn) |
237 | - logger.debug("asserting checkbox checked") |
238 | - self.assertThat(checkboxBtn.checked, Eventually(Equals(True))) |
239 | - |
240 | - #save selected feedname |
241 | - feedName = self.main_view.strip_html_tags( |
242 | - str(self.main_view.get_append_page_list_items()[0].text)) |
243 | - |
244 | - #click on Next button |
245 | - logger.debug("asserting next") |
246 | - self.assertThat(self.main_view.get_next_button, |
247 | - Eventually(Not(Is(None)))) |
248 | - logger.debug("grabbing next") |
249 | - nextButton = self.main_view.get_next_button() |
250 | - logger.debug("clicking next") |
251 | - self.pointing_device.click_object(nextButton) |
252 | - |
253 | - #verify choose topic page has opened |
254 | - logger.debug("asserting choose topic page") |
255 | - chossetopicpage = lambda: self.main_view.get_topics_page().visible |
256 | - self.assertThat(chossetopicpage, Eventually(Equals(True))) |
257 | - |
258 | - #get current topics |
259 | - logger.debug("grabbing topics") |
260 | - topics = self.main_view.get_choose_topics_items() |
261 | - numTopics = len(topics) |
262 | - logger.debug("found " + str(numTopics) + " topics") |
263 | - for topic in topics: |
264 | - logger.debug("Topic: " + str(topic.text)) |
265 | - |
266 | - #add a new topic |
267 | - logger.debug("input topic") |
268 | - self._input_new_topic(topicName) |
269 | - |
270 | - #wait for new feed and topic to be added |
271 | + def add_feed_to_new_topic(self, feed_url, feed_title, topic): |
272 | + add_feeds_page = self.main_view.go_to_add_feeds() |
273 | + # XXX here we are using an external server because we are currently |
274 | + # using the Google Feed API, which doesn't let us access local |
275 | + # resources. --elopio - 2014-02-26 |
276 | + add_feeds_page.search_feed(feed_url) |
277 | + add_feeds_page.select_results(feed_title) |
278 | + choose_topics_page = add_feeds_page.click_next() |
279 | + choose_topics_page.add_topic(topic) |
280 | + # TODO move this wait to the main view custom proxy object. |
281 | + # --elopio - 2014-02-26 |
282 | self._wait_for_refresh() |
283 | |
284 | - return feedName |
285 | + def test_add_feed_to_new_topic(self): |
286 | + """Test that adding a feed to a new topic must show it in a new tab.""" |
287 | + test_feed_url = 'http://www.canonical.com/rss.xml' |
288 | + test_feed_title = 'Insights' |
289 | + test_topic = 'Test topic' |
290 | + self.add_feed_to_new_topic(test_feed_url, test_feed_title, test_topic) |
291 | + |
292 | + selected_tab_title = self.main_view.get_selected_tab_title() |
293 | + self.assertEqual('Test topic', selected_tab_title) |
294 | |
295 | def _remove_feed(self, feedName, topicName): |
296 | logger.debug("removing feed") |
297 | @@ -268,55 +226,32 @@ |
298 | poll += 1 |
299 | return topic |
300 | |
301 | - def test_add_remove_feed_and_topic(self): |
302 | + def test_remove_feed_and_topic(self): |
303 | """ test add and remove feed and topic""" |
304 | - |
305 | - #add topic and feed |
306 | - #TODO, try several different feeds |
307 | - feed = "http://www.canonical.com/rss.xml" |
308 | - feedName = "Insights" |
309 | - topicName = "CanonicalTopic" |
310 | - |
311 | - #just for timing issues |
312 | - self.assertThat(self.main_view.get_shorts_tab(), |
313 | - NotEquals(None)) |
314 | - self.assertThat(self.main_view.get_shorts_tab().objectName, |
315 | - Eventually(Equals("Tab0"))) |
316 | - self.assertThat(self.main_view.get_shorts_tab().visible, |
317 | - Eventually(Equals(True))) |
318 | - |
319 | - #add feed and topic |
320 | - feedName = self._add_feed_and_topic(feed, topicName) |
321 | + test_feed_url = 'http://www.canonical.com/rss.xml' |
322 | + test_feed_title = 'Insights' |
323 | + test_topic = 'Test topic' |
324 | + self.add_feed_to_new_topic(test_feed_url, test_feed_title, test_topic) |
325 | |
326 | #remove added feed |
327 | logger.debug("starting remove feed") |
328 | |
329 | - self._remove_feed(feedName, topicName) |
330 | + self._remove_feed(test_feed_title, test_topic) |
331 | |
332 | #remove added topic |
333 | - self._remove_topic(topicName) |
334 | + self._remove_topic(test_topic) |
335 | |
336 | @unittest.skip("Tab switching fails") |
337 | def test_view_mode_and_feed_item(self): |
338 | """test view modes and ensure feed items can be opened""" |
339 | - |
340 | - feed = "http://www.canonical.com/rss.xml" |
341 | - #feedName = "Insights" |
342 | - topicName = "CanonicalTopic" |
343 | - |
344 | - #just for timing issues |
345 | - self.assertThat(self.main_view.get_shorts_tab(), |
346 | - NotEquals(None)) |
347 | - self.assertThat(self.main_view.get_shorts_tab().objectName, |
348 | - Eventually(Equals("Tab0"))) |
349 | - self.assertThat(self.main_view.get_shorts_tab().visible, |
350 | - Eventually(Equals(True))) |
351 | - |
352 | - #add topic and feed |
353 | - self._add_feed_and_topic(feed, topicName) |
354 | + test_feed_url = 'http://www.canonical.com/rss.xml' |
355 | + test_feed_title = 'Insights' |
356 | + test_topic = 'Test topic' |
357 | + |
358 | + self.add_feed_to_new_topic(test_feed_url, test_feed_title, test_topic) |
359 | |
360 | #verify we are on the editTopic Tab |
361 | - editTab = self.main_view.get_topic_tab(topicName) |
362 | + editTab = self.main_view.get_topic_tab(test_topic) |
363 | self.assertThat(lambda: editTab.visible, Eventually(Equals(True))) |
364 | |
365 | #open toolbar |
366 | @@ -344,9 +279,9 @@ |
367 | #self.assertThat(lambda: feedTab.visible, Eventually(Equals(True))) |
368 | |
369 | #select feed entry |
370 | - self.assertThat(lambda: self.main_view.get_feedlist(topicName), |
371 | + self.assertThat(lambda: self.main_view.get_feedlist(test_topic), |
372 | Eventually(Not(Is(None)))) |
373 | - editFeed = self.main_view.get_feedlist(topicName) |
374 | + editFeed = self.main_view.get_feedlist(test_topic) |
375 | |
376 | for item in editFeed: |
377 | label = item.select_single("Label", objectName="labelFeedname") |
378 | @@ -362,16 +297,14 @@ |
379 | @unittest.skip("Can't see or get dynamic tabs") |
380 | def test_edit_topic(self): |
381 | """test edit topic""" |
382 | - |
383 | - feed = "http://www.canonical.com/rss.xml" |
384 | - feedName = "Insights" |
385 | - topicName = "CanonicalTopic" |
386 | - |
387 | - #add topic and feed |
388 | - feedName = self._add_feed_and_topic(feed, topicName) |
389 | + test_feed_url = 'http://www.canonical.com/rss.xml' |
390 | + test_feed_title = 'Insights' |
391 | + test_topic = 'Test topic' |
392 | + |
393 | + self.add_feed_to_new_topic(test_feed_url, test_feed_title, test_topic) |
394 | |
395 | #verify we are on the topicName Tab |
396 | - editTab = self.main_view.get_topic_tab(topicName) |
397 | + editTab = self.main_view.get_topic_tab(test_topic) |
398 | self.assertThat(editTab.visible, Eventually(Equals(True))) |
399 | |
400 | #open toolbar |
401 | @@ -387,12 +320,12 @@ |
402 | Eventually(Equals("topicmanagement"))) |
403 | |
404 | #verity Tab is expanded |
405 | - editTopic = self.main_view.get_feedlist_topic(topicName) |
406 | + editTopic = self.main_view.get_feedlist_topic(test_topic) |
407 | if editTopic.state != "expended": |
408 | self.pointing_device.click_object(editTopic) |
409 | |
410 | #select feed |
411 | - editFeed = self.main_view.get_feedlist_feed(feedName) |
412 | + editFeed = self.main_view.get_feedlist_feed(test_topic) |
413 | self.assertThat(editFeed, NotEquals(None)) |
414 | self.pointing_device.click_object(editFeed) |
415 |
FAILED: Continuous integration, rev:184 91.189. 93.70:8080/ job/ubuntu- rssreader- app-ci/ 184/ 91.189. 93.70:8080/ job/generic- mediumtests- trusty/ 1524 91.189. 93.70:8080/ job/ubuntu- rssreader- app-raring- amd64-ci/ 184 91.189. 93.70:8080/ job/ubuntu- rssreader- app-saucy- amd64-ci/ 184 91.189. 93.70:8080/ job/ubuntu- rssreader- app-trusty- amd64-ci/ 71
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/ubuntu- rssreader- app-ci/ 184/rebuild
http://