The project includes a dedicated test file,Documentation Index
Fetch the complete documentation index at: https://mintlify.com/DJERLO/Simple-Discord-Music-Bot-Using-Nextcord/llms.txt
Use this file to discover all available pages before exploring further.
test_bot.py, that exercises the core slash command callbacks and the QueueView pagination component. Because Discord command handlers are async functions, the suite relies on pytest-asyncio to drive the event loop. A watchdog runner (pytest-watch) is also available to automatically re-run tests whenever a source file changes, making it straightforward to get tight feedback during development.
pytest-asyncio is required for every async test function in this suite. Without it, async tests are silently skipped or raise collection errors rather than running.Testing Stack
The three testing packages are declared inrequirements.txt:
requirements.txt
| Package | Role |
|---|---|
pytest | Test runner and assertion engine |
pytest-asyncio | Runs async def test functions inside an event loop |
pytest-watch (ptw) | Watchdog that re-runs pytest on every .py file change |
What’s Tested
test_bot.py covers the main slash command callbacks in bot.py and the QueueView class in views.py.
test_queue_view_pagination_logic
Verifies that
QueueView correctly calculates page slices, disables the Prev button on page one, enables the Next button when more pages exist, and sets the correct footer text.test_skip_command_playing
Mocks the voice client and confirms that
vc.skip() is called and the appropriate response message is sent.test_pause_command_success
Confirms that
vc.pause(True) is called when a track is playing and the bot is in a voice channel.test_resume_command_success
Confirms that
vc.pause(False) is called when the player is in a paused state.test_clearqueue_command
Verifies that
vc.queue.clear() is invoked and the confirmation message is sent.test_shuffle_command_success
Verifies that
vc.queue.shuffle() is invoked when the queue is non-empty.test_stop_command_success
Asserts that
vc.disconnect(), vc.queue.clear(), ACTIVE_PLAYERS cleanup, and presence reset all occur together.test_play_command_new_connection
Patches
wavelink.Playable.search, mocks a new voice connection, and verifies that queue.put_wait and vc.play are both called.test_play_command_no_results
Verifies that when
wavelink.Playable.search returns an empty list, queue.put_wait and vc.play are not called.test_nowplaying_command_playing
Asserts that the embed has the title
"💿 Currently Playing" and that the Artist field value matches the mocked track’s author.test_ping_command
Patches
bot.latency to 0.05 and confirms the response message contains the formatted latency "Pong! Latency: 50ms".Test Fixtures
Fixtures intest_bot.py provide shared mock objects and automatic cleanup so each test starts with a predictable state.
| Fixture | Scope | Description |
|---|---|---|
songs | function | List of 3 tuples (url, title, artwork, duration) used to seed QueueView |
mock_track | function | MagicMock(spec=wavelink.Playable) with title="Test Song" and length=180000 |
mock_user | function | MagicMock(spec=nextcord.User) with id=12345, display_name="TestUser", avatar=None |
guild_id | function | String "987654321" representing a fake Discord guild ID |
mock_bot_presence (autouse) | function | Patches bot.bot.change_presence with AsyncMock; auto-applied to every test |
clean_active_players (autouse) | function | Calls bot.ACTIVE_PLAYERS.clear() before and after each test; auto-applied to every test |
autouse fixtures ensure that bot presence calls are intercepted (preventing real Discord API calls) and that the global ACTIVE_PLAYERS dict never leaks state between tests.
Example Test
The pagination test below illustrates how fixtures,QueueView, and plain assert statements combine:
test_bot.py
songs fixture provides 3 tracks. With per_page=2, page 0 should show songs 1–2 and disable the Prev button while keeping Next active. Song Gamma must not appear until page 1.
Running Tests
To run the full suite:Watchdog Mode (Development)
pytest-watch wraps pytest and uses filesystem events to detect when any .py file is written. As soon as a change is saved, the suite re-runs automatically. This makes it easy to catch regressions the instant they are introduced rather than discovering them at a manual test run later.
To restrict ptw to a specific directory (for example, to avoid re-running on every log file write):