From 876071a7a41ee4a1f579739b242a00058bdc160d Mon Sep 17 00:00:00 2001 From: Eddy Pedroni Date: Tue, 25 Feb 2025 13:04:44 +0100 Subject: Refactor song selection tests, change behaviour so first added song is automatically selected --- solo-tool-project/src/solo_tool/solo_tool.py | 2 + .../solo_tool/solo_tool_songs_integrationtest.py | 112 +++++++++++++++++++++ .../test/midi_launchpad_mini_integrationtest.py | 3 - .../test/solo_tool_integrationtest.py | 87 +--------------- 4 files changed, 116 insertions(+), 88 deletions(-) create mode 100644 solo-tool-project/src/solo_tool/solo_tool_songs_integrationtest.py (limited to 'solo-tool-project') diff --git a/solo-tool-project/src/solo_tool/solo_tool.py b/solo-tool-project/src/solo_tool/solo_tool.py index 199e2ad..f5b05c0 100644 --- a/solo-tool-project/src/solo_tool/solo_tool.py +++ b/solo-tool-project/src/solo_tool/solo_tool.py @@ -33,6 +33,8 @@ class SoloTool: raise FileNotFoundError(path) self._songs.append(path) self._keyPoints.append([]) + if self.song is None: + self.song = 0 @property def song(self) -> int: diff --git a/solo-tool-project/src/solo_tool/solo_tool_songs_integrationtest.py b/solo-tool-project/src/solo_tool/solo_tool_songs_integrationtest.py new file mode 100644 index 0000000..0023d81 --- /dev/null +++ b/solo-tool-project/src/solo_tool/solo_tool_songs_integrationtest.py @@ -0,0 +1,112 @@ +import pathlib +import shutil +import pytest + +from solo_tool.solo_tool import SoloTool +from player_mock import Player as MockPlayer + +@pytest.fixture +def mockPlayer(): + return MockPlayer() + +@pytest.fixture +def uut(mockPlayer): + return SoloTool(player=mockPlayer) + +@pytest.fixture +def testSongs(): + return [ + "test.flac", + "test.mp3" + ] + +def test_songSelectionFlow(uut, mockPlayer, testSongs): + # Initially, song list is empty and no song is selected + assert uut.song is None + assert mockPlayer.currentSong == None + assert uut.songs == [] + + # When the first song is added, it is selected automatically + uut.addSong(testSongs[0]) + assert uut.song == 0 + assert mockPlayer.currentSong == testSongs[0] + assert uut.songs == testSongs[0:1] + + # Subsequently added songs are not selected automatically + # Song list order is addition order + for i, song in enumerate(testSongs[1:]): + uut.addSong(testSongs[1]) + assert uut.song == 0 + assert mockPlayer.currentSong == testSongs[0] + assert uut.songs == testSongs[0:i + 2] + + # Songs are selected by index + for i, s in enumerate(uut.songs): + uut.song = i + assert uut.song == i + assert mockPlayer.currentSong == uut.songs[i] + +def test_songSelectionSanitization(uut, mockPlayer, testSongs): + for song in testSongs: + uut.addSong(song) + + # Modifying the song list directly has no effect + uut.songs.append("something") + assert uut.songs == testSongs + assert mockPlayer.currentSong == testSongs[0] + + # The current song cannot be de-selected + uut.song = None + assert uut.song == 0 + assert mockPlayer.currentSong == testSongs[0] + + # Non-existent songs cannot be selected + uut.song = -1 + assert uut.song == 0 + assert mockPlayer.currentSong == testSongs[0] + + uut.song = len(testSongs) + assert uut.song == 0 + assert mockPlayer.currentSong == testSongs[0] + +def test_addInexistentSong(uut, mockPlayer): + # Songs must exist in the filesystem + song = "not/a/real/file" + + with pytest.raises(FileNotFoundError): + uut.addSong(song) + + assert uut.songs == [] + assert uut.song is None + +def test_songSelectionNotification(uut, testSongs): + called = False + receivedValue = None + def callback(value): + nonlocal called, receivedValue + called = True + receivedValue = value + + uut.registerSongSelectionCallback(callback) + assert not called + + # Adding the first song triggers because the song is automatically selected + uut.addSong(songs[0]) + assert called + assert receivedValue == 0 + called = False + + # Adding more songs does not trigger since the selection doesn't change + for song in testSongs: + uut.addSong(song) + assert not called + + # Selecting another song triggers + uut.song = 1 + assert called + assert receivedValue == 1 + called = False + + # Selecting the currently selected song does not trigger + uut.song = 1 + assert not called diff --git a/solo-tool-project/test/midi_launchpad_mini_integrationtest.py b/solo-tool-project/test/midi_launchpad_mini_integrationtest.py index 9e8c92e..642733d 100644 --- a/solo-tool-project/test/midi_launchpad_mini_integrationtest.py +++ b/solo-tool-project/test/midi_launchpad_mini_integrationtest.py @@ -138,10 +138,7 @@ def test_previousAndNextSongButtons(uut, midiWrapperMock, soloTool, playerMock): soloTool.addSong(s) uut.connect() - assert playerMock.currentSong == None - midiWrapperMock.simulateInput(nextSongButton) assert playerMock.currentSong == songs[0] - midiWrapperMock.simulateInput(nextSongButton) assert playerMock.currentSong == songs[1] diff --git a/solo-tool-project/test/solo_tool_integrationtest.py b/solo-tool-project/test/solo_tool_integrationtest.py index 3d7d20f..e63ea3f 100644 --- a/solo-tool-project/test/solo_tool_integrationtest.py +++ b/solo-tool-project/test/solo_tool_integrationtest.py @@ -107,48 +107,7 @@ def test_sanitizePlaybackVolume(uut): uut.volume = 150.0 assert uut.volume == 150.0 -def test_addAndSelectSongs(uut, mockPlayer): - songs = [ - "test.mp3", - "test.flac" - ] - - # Songs are added one by one - for song in songs: - uut.addSong(song) - - # Songs are not selected automatically - assert mockPlayer.currentSong == None - assert uut.song == None - - # Song order is preserved - assert uut.songs == songs - - # Modifying the song list directly has no effect - uut.songs.append("something") - assert uut.songs == songs - - # Songs are selected by index - for i, s in enumerate(uut.songs): - uut.song = i - assert mockPlayer.currentSong == uut.songs[i] - assert uut.song == i - - # The current song cannot be de-selected - uut.song = None - assert uut.song == len(uut.songs) - 1 - - # Non-existent songs cannot be selected - uut.song = -1 - assert uut.song == len(uut.songs) - 1 - - uut.song = 2 - assert uut.song == len(uut.songs) - 1 - def test_addAndJumpToKeyPoints(uut, mockPlayer): - uut.addSong("test.flac") - uut.addSong("test.mp3") - def checkJump(before, expectedAfter): mockPlayer.position = before uut.jump() @@ -160,7 +119,8 @@ def test_addAndJumpToKeyPoints(uut, mockPlayer): assert uut.keyPoints is None assert uut.keyPoint is None - uut.song = 0 + uut.addSong("test.flac") + uut.addSong("test.mp3") # Once a song is selected, jump to start by default assert uut.keyPoint == 0.0 @@ -236,12 +196,6 @@ def test_keyPointsPerSong(uut, mockPlayer): keyPoints.append(1.0) assert 1.0 not in uut.keyPoints -def test_addInexistentSong(uut, mockPlayer): - song = "not/a/real/file" - - with pytest.raises(FileNotFoundError): - uut.addSong(song) - def test_playingStateNotification(uut, mockPlayer): song = "test.flac" uut.addSong(song) @@ -333,43 +287,6 @@ def test_playbackRateNotification(uut, mockPlayer): uut.rate = 0.5 assert not called -def test_currentSongNotification(uut): - called = False - receivedValue = None - def callback(value): - nonlocal called, receivedValue - called = True - receivedValue = value - - uut.registerCurrentSongCallback(callback) - assert not called - - songs = [ - "test.flac", - "test.mp3" - ] - - # Adding a song does not trigger a notification - uut.addSong(songs[0]) - assert not called - - # Selecting a song for the first time triggers - uut.song = 0 - assert called - assert receivedValue == 0 - called = False - - uut.addSong(songs[1]) - assert not called - - # Selecting the same song does not trigger - uut.song = 0 - assert not called - - uut.song = 1 - assert called - assert receivedValue == 1 - called = False def test_currentKeyPointNotification(uut): called = False -- cgit v1.2.3