Merge lp:~gerlowskija/music-app/repeat_button_autopilot_tests into lp:music-app/trusty

Proposed by Jason
Status: Merged
Approved by: Victor Thompson
Approved revision: 413
Merged at revision: 422
Proposed branch: lp:~gerlowskija/music-app/repeat_button_autopilot_tests
Merge into: lp:music-app/trusty
Diff against target: 209 lines (+118/-31)
1 file modified
tests/autopilot/music_app/tests/test_music.py (+118/-31)
To merge this branch: bzr merge lp:~gerlowskija/music-app/repeat_button_autopilot_tests
Reviewer Review Type Date Requested Status
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Victor Thompson Approve
Review via email: mp+214870@code.launchpad.net

Commit message

* Add Autopilot tests for repeat functionality
* Add utility functions for shuffle and repeat

Description of the change

This branch adds 4 autopilot tests to the music_app test suite, that test the behavior seen when moving between songs with the "Repeat" option toggled on.

My first stab at autopilot tests, so I'd appreciate some feedback/help where I'm sure I messed up.

To post a comment you must log in.
Revision history for this message
Jason (gerlowskija) wrote :

A few notes about this branch:

1) I wrote some utility functions for code that I saw reqpeated frequently across the 4 tests I added. When I did this, I also
replaced code in existing tests to use the new utility method where appropriate. I figured this was small enough to leave in the same commit/revision, but if it should be in its own, I can do that too.

2) I had trouble determining programmatically what the first and last songs in a given "Now Playing" queue were. (I was able to get a list of songs in the queue relatively easy, but since select_many() returns results in an indeterminate order, I had trouble using it to determine where songs came in the queue.) So I had to hardcode what I expected the songs to be (see the FIRST_TITLE and LAST_TITLE constants). I'd like to avoid having these hardcoded values; does anyone have any advice on how to get an ordered list of songs/titles in the Now Playing queue?

Revision history for this message
Victor Thompson (vthompson) wrote :

The added tests pass on the device. I'll do a more in depth review later on tonight.

Revision history for this message
Victor Thompson (vthompson) wrote :

Thanks Jason! Could we use your turn_shuffle_off() utility function for the test_shuffle test?

Other than that I think this looks good. We can investigate what we do with the "next when repeat on" and "previous when repeat on" tests once the media hub capability lands. Good work! :)

review: Needs Information
Revision history for this message
Jason (gerlowskija) wrote :

Thanks for taking a look Victor; I'm glad to help! Or try at least : )

I'm pretty sure my change already has the turn_shuffle_off() function being used in the test_shuffle test you mentioned. You can see it at line 310 of the test_music.py (or line 104 in the diff below). It's pretty possible I'm just missing a spot, or looking in the wrong place, so feel free to double check me, but I think the call is already used there.

Let me know if there's anything I can change, or any other comments you have.

Jason

Revision history for this message
Victor Thompson (vthompson) wrote :

See around L290:

            #ensure shuffle is on
            if not self.player.shuffle:
                logger.debug("Turning on shuffle")
                self.pointing_device.click_object(shufflebutton)
            else:
                logger.debug("Shuffle already on")
            self.assertThat(self.player.shuffle, Eventually(Equals(True)))

Or just search for "shufflebutton". In the same regard, you can delete L255 (but this was a pointless line of code before your changes--so feel free to disregard this suggestion):

        shufflebutton = self.main_view.get_shuffle_button()

Revision history for this message
Jason (gerlowskija) wrote :

Oh I see. I didn't make a utility to turn shuffle on, since in the tests I
added I just needed to turn it off. But it makes sense to add a function
for it, and add it in. Good catch! I'll push up a revised change in a bit.

On Thu, Apr 10, 2014 at 10:11 PM, Victor Thompson <<email address hidden>
> wrote:

> See around L290:
>
> #ensure shuffle is on
> if not self.player.shuffle:
> logger.debug("Turning on shuffle")
> self.pointing_device.click_object(shufflebutton)
> else:
> logger.debug("Shuffle already on")
> self.assertThat(self.player.shuffle, Eventually(Equals(True)))
>
>
> Or just search for "shufflebutton". In the same regard, you can delete
> L255 (but this was a pointless line of code before your changes--so feel
> free to disregard this suggestion):
>
> shufflebutton = self.main_view.get_shuffle_button()
>
>
> --
>
> https://code.launchpad.net/~gerlowskija/music-app/repeat_button_autopilot_tests/+merge/214870
> You are the owner of
> lp:~gerlowskija/music-app/repeat_button_autopilot_tests.
>

Revision history for this message
Victor Thompson (vthompson) wrote :

This looks good and everything passed on my device. Thanks Jason!

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

FAILED: Autolanding.
No commit message was specified in the merge proposal. Hit 'Add commit message' on the merge proposal web page or follow the link below. You can approve the merge proposal yourself to rerun.
https://code.launchpad.net/~gerlowskija/music-app/repeat_button_autopilot_tests/+merge/214870/+edit-commit-message

review: Needs Fixing (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Victor Thompson (vthompson) wrote :

Jason,

There are a few things that need fixing. Pep8 is a program that checks python coding standards. You can check this by installing 'pep8' and running it against the python source like so:

$ pep8 tests/autopilot/music_app/tests/test_music.py

tests/autopilot/music_app/tests/test_music.py:40:80: E501 line too long (83 > 79 characters)
tests/autopilot/music_app/tests/test_music.py:621:80: E501 line too long (80 > 79 characters)
tests/autopilot/music_app/tests/test_music.py:654:80: E501 line too long (80 > 79 characters)

Here's what the Jenkins CI infrastructure sees as the issue:

+ pep8 --repeat --show-source .
./tests/autopilot/music_app/tests/test_music.py:40:80: E501 line too long (83 > 79 characters)
        song = self.main_view.get_album_sheet_listview_tracktitle(self.FIRST_TITLE)
                                                                               ^
./tests/autopilot/music_app/tests/test_music.py:621:80: E501 line too long (80 > 79 characters)
        """With repeat on, the first song should play after the last one ends"""
                                                                               ^
./tests/autopilot/music_app/tests/test_music.py:654:80: E501 line too long (80 > 79 characters)
        """With repeat on, 'previous' from the first song plays the last one."""
                                                                               ^
./debian/tmp/usr/lib/python2.7/dist-packages/music_app/tests/test_music.py:40:80: E501 line too long (83 > 79 characters)
        song = self.main_view.get_album_sheet_listview_tracktitle(self.FIRST_TITLE)
                                                                               ^
./debian/tmp/usr/lib/python2.7/dist-packages/music_app/tests/test_music.py:621:80: E501 line too long (80 > 79 characters)
        """With repeat on, the first song should play after the last one ends"""
                                                                               ^
./debian/tmp/usr/lib/python2.7/dist-packages/music_app/tests/test_music.py:654:80: E501 line too long (80 > 79 characters)
        """With repeat on, 'previous' from the first song plays the last one."""
                                                                               ^
./debian/music-app-autopilot/usr/lib/python2.7/dist-packages/music_app/tests/test_music.py:40:80: E501 line too long (83 > 79 characters)
        song = self.main_view.get_album_sheet_listview_tracktitle(self.FIRST_TITLE)
                                                                               ^
./debian/music-app-autopilot/usr/lib/python2.7/dist-packages/music_app/tests/test_music.py:621:80: E501 line too long (80 > 79 characters)
        """With repeat on, the first song should play after the last one ends"""
                                                                               ^
./debian/music-app-autopilot/usr/lib/python2.7/dist-packages/music_app/tests/test_music.py:654:80: E501 line too long (80 > 79 characters)
        """With repeat on, 'previous' from the first song plays the last one."""

review: Needs Fixing
Revision history for this message
Jason (gerlowskija) wrote :

Ok, sounds easy enough. Just as a process question, should I make those changes as their own commit/revision, or is there a way to edit the branch I've already pushed to contain those changes in the original commit itself?

> Jason,
>
> There are a few things that need fixing. Pep8 is a program that checks python
> coding standards. You can check this by installing 'pep8' and running it
> against the python source like so:
>
> $ pep8 tests/autopilot/music_app/tests/test_music.py
>
> tests/autopilot/music_app/tests/test_music.py:40:80: E501 line too long (83 >
> 79 characters)
> tests/autopilot/music_app/tests/test_music.py:621:80: E501 line too long (80 >
> 79 characters)
> tests/autopilot/music_app/tests/test_music.py:654:80: E501 line too long (80 >
> 79 characters)
>
> Here's what the Jenkins CI infrastructure sees as the issue:
>
> + pep8 --repeat --show-source .
> ./tests/autopilot/music_app/tests/test_music.py:40:80: E501 line too long (83
> > 79 characters)
> song =
> self.main_view.get_album_sheet_listview_tracktitle(self.FIRST_TITLE)
> ^
> ./tests/autopilot/music_app/tests/test_music.py:621:80: E501 line too long (80
> > 79 characters)
> """With repeat on, the first song should play after the last one
> ends"""
> ^
> ./tests/autopilot/music_app/tests/test_music.py:654:80: E501 line too long (80
> > 79 characters)
> """With repeat on, 'previous' from the first song plays the last
> one."""
> ^
> ./debian/tmp/usr/lib/python2.7/dist-
> packages/music_app/tests/test_music.py:40:80: E501 line too long (83 > 79
> characters)
> song =
> self.main_view.get_album_sheet_listview_tracktitle(self.FIRST_TITLE)
> ^
> ./debian/tmp/usr/lib/python2.7/dist-
> packages/music_app/tests/test_music.py:621:80: E501 line too long (80 > 79
> characters)
> """With repeat on, the first song should play after the last one
> ends"""
> ^
> ./debian/tmp/usr/lib/python2.7/dist-
> packages/music_app/tests/test_music.py:654:80: E501 line too long (80 > 79
> characters)
> """With repeat on, 'previous' from the first song plays the last
> one."""
> ^
> ./debian/music-app-autopilot/usr/lib/python2.7/dist-
> packages/music_app/tests/test_music.py:40:80: E501 line too long (83 > 79
> characters)
> song =
> self.main_view.get_album_sheet_listview_tracktitle(self.FIRST_TITLE)
> ^
> ./debian/music-app-autopilot/usr/lib/python2.7/dist-
> packages/music_app/tests/test_music.py:621:80: E501 line too long (80 > 79
> characters)
> """With repeat on, the first song should play after the last one
> ends"""
> ^
> ./debian/music-app-autopilot/usr/lib/python2.7/dist-
> packages/music_app/tests/test_music.py:654:80: E501 line too long (80 > 79
> characters)
> """With repeat on, 'previous' from the first song plays the last
> one."""

Revision history for this message
Victor Thompson (vthompson) wrote :

You can use as many commits as you need. When Jenkins merges this branch it uses the commit message at the top of the page under "Commit Message". So, just continue to push your changes to lp:~gerlowskija/music-app/repeat_button_autopilot_tests and you should be good to go!

Revision history for this message
Victor Thompson (vthompson) wrote :

Looks good, thanks Jason!

review: Approve
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Victor Thompson (vthompson) wrote :

Sorry Jason, pyflakes is another coding standard type program and it has complained about the following:

+ pyflakes .
./tests/autopilot/music_app/tests/test_music.py:12: 'sys' imported but unused
./tests/autopilot/music_app/tests/test_music.py:217: local variable 'shufflebutton' is assigned to but never used
./debian/tmp/usr/lib/python2.7/dist-packages/music_app/tests/test_music.py:12: 'sys' imported but unused
./debian/tmp/usr/lib/python2.7/dist-packages/music_app/tests/test_music.py:217: local variable 'shufflebutton' is assigned to but never used
./debian/music-app-autopilot/usr/lib/python2.7/dist-packages/music_app/tests/test_music.py:12: 'sys' imported but unused
./debian/music-app-autopilot/usr/lib/python2.7/dist-packages/music_app/tests/test_music.py:217: local variable 'shufflebutton' is assigned to but never used

I think you need to delete the two lines of code it points out.

review: Needs Fixing
413. By Jason

Remove unused variable and import

Revision history for this message
Jason (gerlowskija) wrote :

It's no problem, they were things I should have caught anyway. Are pep8 and pyflakes run on all the core app builds (just for future reference)? Are there any other checks I should be doing before I push a branch?

> Sorry Jason, pyflakes is another coding standard type program and it has
> complained about the following:
>
> + pyflakes .
> ./tests/autopilot/music_app/tests/test_music.py:12: 'sys' imported but unused
> ./tests/autopilot/music_app/tests/test_music.py:217: local variable
> 'shufflebutton' is assigned to but never used
> ./debian/tmp/usr/lib/python2.7/dist-packages/music_app/tests/test_music.py:12:
> 'sys' imported but unused
> ./debian/tmp/usr/lib/python2.7/dist-
> packages/music_app/tests/test_music.py:217: local variable 'shufflebutton' is
> assigned to but never used
> ./debian/music-app-autopilot/usr/lib/python2.7/dist-
> packages/music_app/tests/test_music.py:12: 'sys' imported but unused
> ./debian/music-app-autopilot/usr/lib/python2.7/dist-
> packages/music_app/tests/test_music.py:217: local variable 'shufflebutton' is
> assigned to but never used
>
> I think you need to delete the two lines of code it points out.

Revision history for this message
Victor Thompson (vthompson) wrote :

Approved, thanks! Currently I think it's just pep8 and pyflakes that check the python source.

review: Approve
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/music_app/tests/test_music.py'
2--- tests/autopilot/music_app/tests/test_music.py 2014-04-02 00:19:32 +0000
3+++ tests/autopilot/music_app/tests/test_music.py 2014-04-12 14:31:41 +0000
4@@ -21,6 +21,8 @@
5
6
7 class TestMainWindow(MusicTestCase):
8+ FIRST_TITLE = "Foss Yeaaaah! (Radio Edit)"
9+ LAST_TITLE = "TestMP3Title"
10
11 def setUp(self):
12 super(TestMainWindow, self).setUp()
13@@ -30,6 +32,50 @@
14 spinner = lambda: self.main_view.get_spinner().running
15 self.assertThat(spinner, Eventually(Equals(False)))
16
17+ def populate_and_play_queue(self):
18+ first_genre_item = self.main_view.get_first_genre_item()
19+ self.pointing_device.click_object(first_genre_item)
20+
21+ title = self.FIRST_TITLE
22+ song = self.main_view.get_album_sheet_listview_tracktitle(title)
23+ self.pointing_device.click_object(song)
24+
25+ def turn_shuffle_off(self):
26+ if self.player.shuffle:
27+ shufflebutton = self.main_view.get_shuffle_button()
28+ logger.debug("Turning off shuffle")
29+ self.pointing_device.click_object(shufflebutton)
30+ else:
31+ logger.debug("Shuffle already off")
32+ self.assertThat(self.player.shuffle, Eventually(Equals(False)))
33+
34+ def turn_shuffle_on(self):
35+ if not self.player.shuffle:
36+ shufflebutton = self.main_view.get_shuffle_button()
37+ logger.debug("Turning on shuffle")
38+ self.pointing_device.click_object(shufflebutton)
39+ else:
40+ logger.debug("Shuffle already on")
41+ self.assertThat(self.player.shuffle, Eventually(Equals(True)))
42+
43+ def turn_repeat_off(self):
44+ if self.player.repeat:
45+ repeatbutton = self.main_view.get_repeat_button()
46+ logger.debug("Turning off repeat")
47+ self.pointing_device.click_object(repeatbutton)
48+ else:
49+ logger.debug("Repeat already off")
50+ self.assertThat(self.player.repeat, Eventually(Equals(False)))
51+
52+ def turn_repeat_on(self):
53+ if not self.player.repeat:
54+ repeatbutton = self.main_view.get_repeat_button()
55+ logger.debug("Turning on repeat")
56+ self.pointing_device.click_object(repeatbutton)
57+ else:
58+ logger.debug("Repeat already on")
59+ self.assertThat(self.player.repeat, Eventually(Equals(True)))
60+
61 def test_reads_music_library(self):
62 """ tests if the music library is populated from our
63 fake mediascanner database"""
64@@ -124,14 +170,7 @@
65 self.pointing_device.click_object(playbutton)
66 self.assertThat(self.player.isPlaying, Eventually(Equals(False)))
67
68- #ensure shuffle is off
69- if self.player.shuffle:
70- shufflebutton = self.main_view.get_shuffle_button()
71- logger.debug("Turning off shuffle")
72- self.pointing_device.click_object(shufflebutton)
73- else:
74- logger.debug("Shuffle already off")
75- self.assertThat(self.player.shuffle, Eventually(Equals(False)))
76+ self.turn_shuffle_off()
77
78 """ Select next """
79 #goal is to go back and forth and ensure 2 different songs
80@@ -174,18 +213,11 @@
81 self.pointing_device.click_object(song)
82
83 playbutton = self.main_view.get_now_playing_play_button()
84- shufflebutton = self.main_view.get_shuffle_button()
85
86 title = self.player.currentMetaTitle
87 artist = self.player.currentMetaArtist
88
89- #ensure shuffle is off
90- if self.player.shuffle:
91- logger.debug("Turning off shuffle")
92- self.pointing_device.click_object(shufflebutton)
93- self.assertThat(self.player.shuffle, Eventually(Equals(False)))
94- else:
95- logger.debug("Shuffle already off")
96+ self.turn_shuffle_off()
97
98 """ Track is playing """
99 count = 1
100@@ -228,7 +260,6 @@
101 self.pointing_device.click_object(song)
102
103 """ Track is playing, shuffle is turned on"""
104- shufflebutton = self.main_view.get_shuffle_button()
105 forwardbutton = self.main_view.get_forward_button()
106 playbutton = self.main_view.get_now_playing_play_button()
107 previousbutton = self.main_view.get_previous_button()
108@@ -261,13 +292,7 @@
109 if (not self.main_view.toolbarShown):
110 self.main_view.show_toolbar()
111
112- #ensure shuffle is on
113- if not self.player.shuffle:
114- logger.debug("Turning on shuffle")
115- self.pointing_device.click_object(shufflebutton)
116- else:
117- logger.debug("Shuffle already on")
118- self.assertThat(self.player.shuffle, Eventually(Equals(True)))
119+ self.turn_shuffle_on()
120
121 self.pointing_device.click_object(forwardbutton)
122 self.assertThat(self.player.isPlaying,
123@@ -283,13 +308,7 @@
124 self.assertThat(self.player.isPlaying,
125 Eventually(Equals(False)))
126
127- #ensure shuffle is off
128- if self.player.shuffle:
129- logger.debug("Turning off shuffle")
130- self.pointing_device.click_object(shufflebutton)
131- else:
132- logger.debug("Shuffle already off")
133- self.assertThat(self.player.shuffle, Eventually(Equals(False)))
134+ self.turn_shuffle_off()
135
136 self.pointing_device.click_object(previousbutton)
137
138@@ -580,3 +599,71 @@
139 # verify song has been deleted
140 finalqueueCount = self.main_view.get_queue_track_count()
141 self.assertThat(finalqueueCount, Equals(initialqueueCount - 1))
142+
143+ def test_playback_stops_when_last_song_ends_and_repeat_off(self):
144+ """Check that playback stops when the last song in the queue ends"""
145+ self.populate_and_play_queue()
146+ self.turn_shuffle_off()
147+ self.turn_repeat_off()
148+
149+ num_tracks = self.main_view.get_queue_track_count()
150+
151+ #Skip through all songs in queue, stopping on last one.
152+ forward_button = self.main_view.get_forward_button()
153+ for count in range(0, num_tracks - 1):
154+ self.pointing_device.click_object(forward_button)
155+
156+ #When the last song ends, playback should stop
157+ self.assertThat(self.player.isPlaying, Eventually(Equals(False)))
158+
159+ def test_playback_repeats_when_last_song_ends_and_repeat_on(self):
160+ """With repeat on, the 1st song should play after the last one ends"""
161+ self.populate_and_play_queue()
162+ self.turn_shuffle_off()
163+ self.turn_repeat_on()
164+
165+ num_titles = self.main_view.get_queue_track_count()
166+ #Skip through all songs in queue, stopping on last one.
167+ forward_button = self.main_view.get_forward_button()
168+ for count in range(0, num_titles - 1):
169+ self.pointing_device.click_object(forward_button)
170+
171+ #Make sure we loop back to first song after last song ends
172+ actual_title = lambda: self.player.currentMetaTitle
173+ self.assertThat(actual_title, Eventually(Equals(self.FIRST_TITLE)))
174+ self.assertThat(self.player.isPlaying, Eventually(Equals(True)))
175+
176+ def test_pressing_next_from_last_song_plays_first_when_repeat_on(self):
177+ """With repeat on, skipping the last song jumps to the first track"""
178+ self.populate_and_play_queue()
179+ self.turn_shuffle_off()
180+ self.turn_repeat_on()
181+
182+ num_titles = self.main_view.get_queue_track_count()
183+ #Skip through all songs in queue, INCLUDING last one.
184+ forward_button = self.main_view.get_forward_button()
185+ for count in range(0, num_titles - 1):
186+ self.pointing_device.click_object(forward_button)
187+
188+ actual_title = lambda: self.player.currentMetaTitle
189+ self.assertThat(actual_title, Eventually(Equals(self.FIRST_TITLE)))
190+ self.assertThat(self.player.isPlaying, Eventually(Equals(True)))
191+
192+ def test_pressing_prev_from_first_song_plays_last_when_repeat_on(self):
193+ """With repeat on, 'previous' from the 1st song plays the last one."""
194+ self.populate_and_play_queue()
195+ self.turn_shuffle_off()
196+ self.turn_repeat_on()
197+
198+ prev_button = self.main_view.get_previous_button()
199+ initial_song = self.player.currentMetaTitle
200+ self.pointing_device.click_object(prev_button)
201+ #If we're far enough into a song, pressing prev just takes us to the
202+ #beginning of that track. In that case, hit prev again to actually
203+ #skip over the track.
204+ if self.player.currentMetaTitle == initial_song:
205+ self.pointing_device.click_object(prev_button)
206+
207+ actual_title = lambda: self.player.currentMetaTitle
208+ self.assertThat(actual_title, Eventually(Equals(self.LAST_TITLE)))
209+ self.assertThat(self.player.isPlaying, Eventually(Equals(True)))

Subscribers

People subscribed via source and target branches

to status/vote changes: