Skip to content

Add automated test suite and CI - #13

Merged
Isma-L154 merged 1 commit into
mainfrom
test/automated-test-suite
Aug 21, 2026
Merged

Add automated test suite and CI#13
Isma-L154 merged 1 commit into
mainfrom
test/automated-test-suite

Conversation

@Isma-L154

Copy link
Copy Markdown
Owner

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.

File Covers
tests/test_player_queue.py add/add_many against MAX_QUEUE, remove/move range validation, shuffle, clear, HISTORY_LIMIT, go_previous ordering, idempotent destroy
tests/test_player_advance.py The _advance state machine: every combination of loop_mode x _skip x _replay, autoplay, idle timeout, and being woken by a late enqueue
tests/test_media_helpers.py Search-prefix routing, sparse yt-dlp info dicts, entry unwrapping, classify_stream_error, kill_stream idempotency
tests/test_checks.py The three voice-state guards, asserting each one explains its refusal rather than failing silently
tests/test_commands.py Command edge cases from the project brief

Edge cases specifically covered

The brief calls out "what happens if a user runs !skip while the queue is empty" and "what if an admin disconnects the bot manually". Both are now tests, along with:

  • !skip / !pause / !resume / !previous / !nowplaying / !queue with no active player
  • !volume at the boundaries (0 and 100 must be accepted) and out of range
  • !play with an over-length query, asserting it is rejected before any yt-dlp work starts
  • !shuffle / !remove on an empty queue
  • Effect commands with nothing playing, and the per-guild effect cooldown
  • Everyone leaving the voice channel, versus a human still being present, versus a bot leaving, versus activity in an unrelated channel

How it works

MusicPlayer normally starts its background loop in __init__. The fake_bot fixture supplies a create_task that closes the coroutine instead of scheduling it, so tests drive _advance and 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.yml runs on push to main and 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

pip install -r requirements-dev.txt
pytest

Expected: 114 passed.

The one warning is DeprecationWarning: 'audioop' is deprecated, raised by discord.py itself on import — not by this code. Worth noting separately: audioop is removed in Python 3.13, so the bot must stay on 3.12 or below until discord.py addresses it.

Notes for review

  • No production code is touched. This PR is tests, CI config and a README section only.
  • Tests assert current correct behaviour. The known bugs are deliberately not encoded here — each gets its own failing test in its own fix PR.

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
@Isma-L154
Isma-L154 merged commit 656c2bd into main Aug 21, 2026
3 checks passed
@Isma-L154
Isma-L154 deleted the test/automated-test-suite branch August 21, 2026 01:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No automated test suite

1 participant