From 025bafc114484ba49816d54cfcb9fa3728f72922 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Sun, 20 Oct 2013 15:41:12 +0200 Subject: [PATCH] local/core: Update random tests to be more predictable - Replace setting the random seed with mocking out shuffle with reverse. This makes tests easier to reason about while still being able to test correct behaviour. - Increases number of tracks to four to avoid test passing due to symetry in plain and reversed lists. - Made test_eot_track_with_random_after_append_playlist actually test eot and not next. - Found a test failure in handling of test_random_until_end_of_playlist, fix in next commit. --- tests/backends/local/playback_test.py | 120 +++++++++++++++++--------- tests/data/song4.wav | Bin 0 -> 35292 bytes 2 files changed, 81 insertions(+), 39 deletions(-) create mode 100644 tests/data/song4.wav diff --git a/tests/backends/local/playback_test.py b/tests/backends/local/playback_test.py index cd67a0e6..63d9b958 100644 --- a/tests/backends/local/playback_test.py +++ b/tests/backends/local/playback_test.py @@ -27,8 +27,12 @@ class LocalPlaybackProviderTest(unittest.TestCase): 'tag_cache_file': path_to_data_dir('empty_tag_cache'), } } + + # We need four tracks so that our shuffled track tests behave nicely with + # reversed as a fake shuffle. Ensuring that shuffled order is [4,3,2,1] and + # normal order [1,2,3,4] which means next_track != next_track_with_random tracks = [ - Track(uri=generate_song(i), length=4464) for i in range(1, 4)] + Track(uri=generate_song(i), length=4464) for i in (1, 2, 3, 4)] def add_track(self, uri): track = Track(uri=uri, length=4464) @@ -320,12 +324,14 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.tracklist.next_track(tl_track), self.tl_tracks[0]) @populate_tracklist - def test_next_track_with_random(self): - random.seed(1) + @mock.patch('random.shuffle') + def test_next_track_with_random(self, shuffle_mock): + shuffle_mock.side_effect = lambda tracks: tracks.reverse() + self.tracklist.random = True - tl_track = self.playback.current_tl_track - self.assertEqual( - self.tracklist.next_track(tl_track), self.tl_tracks[2]) + current_tl_track = self.playback.current_tl_track + next_tl_track = self.tracklist.next_track(current_tl_track) + self.assertEqual(next_tl_track, self.tl_tracks[-1]) @populate_tracklist def test_next_with_consume(self): @@ -343,25 +349,38 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.assertEqual(self.playback.current_track, self.tracks[1]) @populate_tracklist - def test_next_with_random(self): - # FIXME feels very fragile - random.seed(1) + @mock.patch('random.shuffle') + def test_next_with_random(self, shuffle_mock): + shuffle_mock.side_effect = lambda tracks: tracks.reverse() + self.tracklist.random = True self.playback.play() self.playback.next() - self.assertEqual(self.playback.current_track, self.tracks[1]) + self.assertEqual(self.playback.current_track, self.tracks[-2]) @populate_tracklist - def test_next_track_with_random_after_append_playlist(self): - random.seed(1) + @mock.patch('random.shuffle') + def test_next_track_with_random_after_append_playlist(self, shuffle_mock): + shuffle_mock.side_effect = lambda tracks: tracks.reverse() + self.tracklist.random = True - tl_track = self.playback.current_tl_track - self.assertEqual(self.tracklist.next_track(tl_track), - self.tl_tracks[2]) + current_tl_track = self.playback.current_tl_track + + excpected_tl_track = self.tracklist.tl_tracks[-1] + next_tl_track = self.tracklist.next_track(current_tl_track) + + # Baseline checking that first next_track is last tl track per our fake shuffle. + self.assertEqual(next_tl_track, excpected_tl_track) + self.tracklist.add(self.tracks[:1]) - tl_track = self.playback.current_tl_track - self.assertEqual( - self.tracklist.next_track(tl_track), self.tl_tracks[1]) + + old_next_tl_track = next_tl_track + excpected_tl_track = self.tracklist.tl_tracks[-1] + next_tl_track = self.tracklist.next_track(current_tl_track) + + # Verify that first next track has changed since we added to the playlist. + self.assertEqual(next_tl_track, excpected_tl_track) + self.assertNotEqual(next_tl_track, old_next_tl_track) @populate_tracklist def test_end_of_track(self): @@ -475,12 +494,14 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.tracklist.next_track(tl_track), self.tl_tracks[0]) @populate_tracklist - def test_end_of_track_track_with_random(self): - random.seed(1) + @mock.patch('random.shuffle') + def test_end_of_track_track_with_random(self, shuffle_mock): + shuffle_mock.side_effect = lambda tracks: tracks.reverse() + self.tracklist.random = True tl_track = self.playback.current_tl_track self.assertEqual( - self.tracklist.next_track(tl_track), self.tl_tracks[2]) + self.tracklist.next_track(tl_track), self.tl_tracks[-1]) @populate_tracklist def test_end_of_track_with_consume(self): @@ -490,25 +511,39 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.assertNotIn(self.tracks[0], self.tracklist.tracks) @populate_tracklist - def test_end_of_track_with_random(self): - # FIXME feels very fragile - random.seed(1) + @mock.patch('random.shuffle') + def test_end_of_track_with_random(self, shuffle_mock): + shuffle_mock.side_effect = lambda tracks: tracks.reverse() + self.tracklist.random = True self.playback.play() + self.assertEqual(self.playback.current_track, self.tracks[-1]) self.playback.on_end_of_track() - self.assertEqual(self.playback.current_track, self.tracks[1]) + self.assertEqual(self.playback.current_track, self.tracks[-2]) @populate_tracklist - def test_end_of_track_track_with_random_after_append_playlist(self): - random.seed(1) + @mock.patch('random.shuffle') + def test_end_of_track_track_with_random_after_append_playlist(self, shuffle_mock): + shuffle_mock.side_effect = lambda tracks: tracks.reverse() + self.tracklist.random = True - tl_track = self.playback.current_tl_track - self.assertEqual( - self.tracklist.next_track(tl_track), self.tl_tracks[2]) + current_tl_track = self.playback.current_tl_track + + excpected_tl_track = self.tracklist.tl_tracks[-1] + eot_tl_track = self.tracklist.eot_track(current_tl_track) + + # Baseline checking that first eot_track is last tl track per our fake shuffle. + self.assertEqual(eot_tl_track, excpected_tl_track) + self.tracklist.add(self.tracks[:1]) - tl_track = self.playback.current_tl_track - self.assertEqual( - self.tracklist.next_track(tl_track), self.tl_tracks[1]) + + old_eot_tl_track = eot_tl_track + excpected_tl_track = self.tracklist.tl_tracks[-1] + eot_tl_track = self.tracklist.eot_track(current_tl_track) + + # Verify that first next track has changed since we added to the playlist. + self.assertEqual(eot_tl_track, excpected_tl_track) + self.assertNotEqual(eot_tl_track, old_eot_tl_track) @populate_tracklist def test_previous_track_before_play(self): @@ -872,15 +907,19 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.assertEqual(len(self.tracklist.tracks), 0) @populate_tracklist - def test_play_with_random(self): - random.seed(1) + @mock.patch('random.shuffle') + def test_play_with_random(self, shuffle_mock): + shuffle_mock.side_effect = lambda tracks: tracks.reverse() + self.tracklist.random = True self.playback.play() - self.assertEqual(self.playback.current_track, self.tracks[2]) + self.assertEqual(self.playback.current_track, self.tracks[-1]) @populate_tracklist - def test_previous_with_random(self): - random.seed(1) + @mock.patch('random.shuffle') + def test_previous_with_random(self, shuffle_mock): + shuffle_mock.side_effect = lambda tracks: tracks.reverse() + self.tracklist.random = True self.playback.play() self.playback.next() @@ -918,7 +957,10 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.assertEqual(self.tracklist.consume, False) @populate_tracklist - def test_random_until_end_of_playlist(self): + @mock.patch('random.shuffle') + def test_random_until_end_of_playlist(self, shuffle_mock): + shuffle_mock.side_effect = lambda tracks: tracks.reverse() + self.tracklist.random = True self.playback.play() for _ in self.tracks[1:]: diff --git a/tests/data/song4.wav b/tests/data/song4.wav new file mode 100644 index 0000000000000000000000000000000000000000..0041c7ba42b9ae5499f8a73092f66c2a1e024fe1 GIT binary patch literal 35292 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 literal 0 HcmV?d00001