Merge lp:~elopio/ubuntu-rssreader-app/refactor_tests into lp:~ubuntu-shorts-dev/ubuntu-rssreader-app/trunk

Proposed by Leo Arias on 2014-02-27
Status: Merged
Approved by: Nicholas Skaggs on 2014-03-06
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
Reviewer Review Type Date Requested Status
Chris Gagnon (community) 2014-02-27 Approve on 2014-03-05
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve on 2014-03-05
Carla Sella (community) 2014-02-27 Approve on 2014-03-03
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.

To post a comment you must log in.
184. By Leo Arias on 2014-02-27

Fixed the copyright statements.

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://bazaar.launchpad.net/~phablet-team/webbrowser-app/trunk/view/head:/tests/autopilot/webbrowser_app/tests/http_server.py

review: Needs Fixing
Carla Sella (carla-sella) wrote :

I think that writing tests this way is fine.

Carla Sella (carla-sella) :
review: Approve
185. By Leo Arias on 2014-03-04

Removed the old add helper. Updated the remove tests with the new one.

186. By Leo Arias on 2014-03-04

Updated the other tests.

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://developers.google.com/api-client-library/python/guide/mocks

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.

review: Approve

Preview Diff

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

Subscribers

People subscribed via source and target branches