Merge lp:~gerlowskija/music-app/repeat_button_autopilot_tests into lp:music-app/trusty
- repeat_button_autopilot_tests
- Merge into trusty
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 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Victor Thompson | Approve | ||
Review via email:
|
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.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jason (gerlowskija) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Victor Thompson (vthompson) wrote : | # |
The added tests pass on the device. I'll do a more in depth review later on tonight.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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! :)
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Victor Thompson (vthompson) wrote : | # |
See around L290:
#ensure shuffle is on
if not self.player.
else:
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):
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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.
> logger.
> self.pointing_
> else:
> logger.
> self.assertThat
>
>
> 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_
>
>
> --
>
> https:/
> You are the owner of
> lp:~gerlowskija/music-app/repeat_button_autopilot_tests.
>
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Victor Thompson (vthompson) wrote : | # |
This looks good and everything passed on my device. Thanks Jason!
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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
tests/autopilot
tests/autopilot
tests/autopilot
Here's what the Jenkins CI infrastructure sees as the issue:
+ pep8 --repeat --show-source .
./tests/
song = self.main_
./tests/
"""With repeat on, the first song should play after the last one ends"""
./tests/
"""With repeat on, 'previous' from the first song plays the last one."""
./debian/
song = self.main_
./debian/
"""With repeat on, the first song should play after the last one ends"""
./debian/
"""With repeat on, 'previous' from the first song plays the last one."""
./debian/
song = self.main_
./debian/
"""With repeat on, the first song should play after the last one ends"""
./debian/
"""With repeat on, 'previous' from the first song plays the last one."""
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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
>
> tests/autopilot
> 79 characters)
> tests/autopilot
> 79 characters)
> tests/autopilot
> 79 characters)
>
> Here's what the Jenkins CI infrastructure sees as the issue:
>
> + pep8 --repeat --show-source .
> ./tests/
> > 79 characters)
> song =
> self.main_
> ^
> ./tests/
> > 79 characters)
> """With repeat on, the first song should play after the last one
> ends"""
> ^
> ./tests/
> > 79 characters)
> """With repeat on, 'previous' from the first song plays the last
> one."""
> ^
> ./debian/
> packages/
> characters)
> song =
> self.main_
> ^
> ./debian/
> packages/
> characters)
> """With repeat on, the first song should play after the last one
> ends"""
> ^
> ./debian/
> packages/
> characters)
> """With repeat on, 'previous' from the first song plays the last
> one."""
> ^
> ./debian/
> packages/
> characters)
> song =
> self.main_
> ^
> ./debian/
> packages/
> characters)
> """With repeat on, the first song should play after the last one
> ends"""
> ^
> ./debian/
> packages/
> characters)
> """With repeat on, 'previous' from the first song plays the last
> one."""
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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!
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Victor Thompson (vthompson) wrote : | # |
Looks good, thanks Jason!
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Victor Thompson (vthompson) wrote : | # |
Sorry Jason, pyflakes is another coding standard type program and it has complained about the following:
+ pyflakes .
./tests/
./tests/
./debian/
./debian/
./debian/
./debian/
I think you need to delete the two lines of code it points out.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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/
> ./tests/
> 'shufflebutton' is assigned to but never used
> ./debian/
> 'sys' imported but unused
> ./debian/
> packages/
> assigned to but never used
> ./debian/
> packages/
> ./debian/
> packages/
> assigned to but never used
>
> I think you need to delete the two lines of code it points out.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Victor Thompson (vthompson) wrote : | # |
Approved, thanks! Currently I think it's just pep8 and pyflakes that check the python source.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) : | # |
Preview Diff
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))) |
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?