test: add e2e tests for all commands + CI matrix Python 3.12/3.13/3.14#16
Merged
test: add e2e tests for all commands + CI matrix Python 3.12/3.13/3.14#16
Conversation
- Add tests/test_e2e.py with 143 tests covering every command, subcommand, hidden alias, option flag, and global flag (--version, --no-color, NO_COLOR) - Cover play --mode (7 values), --mood (8 moods), vol range validation, history/radio/yt/ai/daemon subcommands, config, update-radios - All daemon I/O mocked — suite runs in ~2s, suitable for pre-commit - Add pytest-e2e local pre-commit hook triggered on cli.py/config.py changes - Bump CI test matrix from 3.10/3.11/3.12 to 3.12/3.13/3.14 (macOS+Linux+Windows) - Exclude windows × 3.14 until pre-release wheels are stable
- Remove continue-on-error: true so test failures actually fail CI - Fix radio tests to mock get_radios_categorized/get_radios/remove_radio (CLI never calls get_stations/remove_station which don't exist) - Fix test_radio_update to return [] from get_new_default_stations (tests "up to date" path instead of hitting click.prompt Abort) - Fix mock_client.get_volume to return int (matches real client return type) - Fix ruff C408: dict() literal, PTH110: Path.exists(), E741: ambiguous l, F841: unused result var; auto-format test_cli.py and music_cli/cli.py
Add targeted # type: ignore comments on lines that had pre-existing mypy errors (hf_cache.py ImportError fallback assignments, cli.py _register_alias calls where click decorators return Group not AliasedGroup). These errors existed on main before this PR but were masked by the ruff formatting failure that blocked mypy from running.
…nments - Change _register_alias signature to accept click.Group (not AliasedGroup) with an internal cast, so all call sites type-check without type: ignore - Use noqa: F811 + type: ignore on hf_cache.py ImportError fallbacks so the ignores suppress errors when hf_hub is installed without triggering unused-ignore when it is absent - Add [[tool.mypy.overrides]] for music_cli.hf_cache to disable warn_unused_ignores for that module only
The pre-commit ruff-format hook was pinned to v0.3.4 while the CI lint job installs the latest ruff (~0.14). This caused pre-commit to reformat files in the CI pre-commit check even though the lint check passed, as the two versions had different formatting opinions on assert-with-message style.
On Windows, NamedTemporaryFile holds a file lock until the with block exits. Calling Path.unlink() inside the with block raises WinError 32 (file in use). Move the unlink to after the with block using try/finally.
The pytest-e2e hook uses language: system, so it runs with whatever Python is on PATH. In the GitHub Actions pre-commit job, pytest is not installed in that Python. Tests are already covered by the test matrix job, so skip pytest-e2e in CI via SKIP env var.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
tests/test_e2e.pywith 143 tests covering every command, subcommand, hidden alias, option flag, and global flagpytest-e2epre-commit hook that runs the fast e2e suite (~2s) on CLI source changes3.10/3.11/3.12→3.12/3.13/3.14across macOS, Linux, and WindowsWhat's covered in
test_e2e.pyTestGlobalFlags--version,--help/-h,--no-color,NO_COLORenv, unknown commandTestAllCommandHelp--helpTestPlayOptions--mode(7 values),--mood(8 moods),--auto,--duration,--index,--sourceTestSimplePlaybackCommandsstop/s,pause/pp,resume/r,next/n,status/stTestVolCommandvolumealiasTestMoodCommandmoodsaliasTestHistoryCommandlist,--limit/-n,play N,haliasTestRadioCommandlist/play/remove/update,radiosaliasTestYtCommandlist/play/remove/clear,youtube+cachedaliasesTestAiCommandlist/play/replay/remove,ai modelsubgroup,modelsaliasTestDaemonCommandstart/stop/restart/statuswith process calls mockedTestConfigCommandTestUpdateRadiosupdate-radiosaliasTestNoColor--no-colorflag,NO_COLOR=1,NO_COLOR=(empty string per spec)TestBareInvocationmctriggers status, doesn't crashTestPlatformSmokeAll daemon I/O is mocked — no FFmpeg, no running daemon, no network required.
CI matrix changes
allow-prereleasestruePre-commit hook
Only triggers when CLI source or the e2e test file is modified.
Test plan
pytest tests/test_e2e.py— 143 passed, ~2s locally (Python 3.12 macOS)pre-commit install && pre-commit run pytest-e2e