Add automated test suite and CI - #13
Merged
Merged
Conversation
The project had no tests, so every change had to be verified by hand in a live Discord server. This adds a pytest suite that runs offline in under a second. Covered: - Queue mutation: add/add_many caps, remove/move range validation, shuffle, clear, history limits, go_previous ordering, idempotent destroy. - The _advance state machine: every combination of loop mode, skip and replay, plus autoplay, the idle timeout, and being woken by a late enqueue. - services.media helpers: search-prefix routing, sparse info dicts, entry unwrapping, error classification, kill_stream idempotency. - Voice-state guards, asserting they explain every refusal. - Command edge cases: empty queue, nothing playing, out-of-range volume, over-length queries, effect throttling, and the bot being left alone in a voice channel. The suite mocks the gateway and never calls yt-dlp, so it needs no credentials, no network and no .env. CI runs it on Python 3.11 and 3.12 (3.12 is what Ubuntu 24.04 ships, which is what the bot is deployed on). Closes #10
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.
Closes #10
Why
The repo had no tests. Every change was verified by hand in a live Discord server, which is slow and — more importantly — never exercises the failure paths that actually break a long-running bot.
This lands the safety net first, before the behavioural fixes queued up in #6, #7 and #8, so those can be reviewed against a suite that already pins down current correct behaviour.
What
pytest+pytest-asyncio, 114 tests, 0.24s, no credentials, no network, no.env.tests/test_player_queue.pyadd/add_manyagainstMAX_QUEUE,remove/moverange validation,shuffle,clear,HISTORY_LIMIT,go_previousordering, idempotentdestroytests/test_player_advance.py_advancestate machine: every combination ofloop_modex_skipx_replay, autoplay, idle timeout, and being woken by a late enqueuetests/test_media_helpers.pyclassify_stream_error,kill_streamidempotencytests/test_checks.pytests/test_commands.pyEdge cases specifically covered
The brief calls out "what happens if a user runs
!skipwhile the queue is empty" and "what if an admin disconnects the bot manually". Both are now tests, along with:!skip/!pause/!resume/!previous/!nowplaying/!queuewith no active player!volumeat the boundaries (0 and 100 must be accepted) and out of range!playwith an over-length query, asserting it is rejected before any yt-dlp work starts!shuffle/!removeon an empty queueHow it works
MusicPlayernormally starts its background loop in__init__. Thefake_botfixture supplies acreate_taskthat closes the coroutine instead of scheduling it, so tests drive_advanceand the queue directly without any voice state. Commands are invoked through.callback(cog, ctx, ...), which runs the real command body against a mocked context.CI
.github/workflows/tests.ymlruns on push tomainand on every PR, against Python 3.11 and 3.12. 3.12 is what Ubuntu 24.04 ships, which is what the bot is deployed on.How to verify
Expected:
114 passed.The one warning is
DeprecationWarning: 'audioop' is deprecated, raised bydiscord.pyitself on import — not by this code. Worth noting separately:audioopis removed in Python 3.13, so the bot must stay on 3.12 or below untildiscord.pyaddresses it.Notes for review