Skip to main content

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.

The project includes a dedicated test file, 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 in requirements.txt:
requirements.txt
pytest
pytest-asyncio
pytest-watch
PackageRole
pytestTest runner and assertion engine
pytest-asyncioRuns 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 in test_bot.py provide shared mock objects and automatic cleanup so each test starts with a predictable state.
FixtureScopeDescription
songsfunctionList of 3 tuples (url, title, artwork, duration) used to seed QueueView
mock_trackfunctionMagicMock(spec=wavelink.Playable) with title="Test Song" and length=180000
mock_userfunctionMagicMock(spec=nextcord.User) with id=12345, display_name="TestUser", avatar=None
guild_idfunctionString "987654321" representing a fake Discord guild ID
mock_bot_presence (autouse)functionPatches bot.bot.change_presence with AsyncMock; auto-applied to every test
clean_active_players (autouse)functionCalls bot.ACTIVE_PLAYERS.clear() before and after each test; auto-applied to every test
The two 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
@pytest.mark.asyncio
async def test_queue_view_pagination_logic(songs, mock_user, guild_id):
    view = QueueView(songs, mock_user, guild_id, per_page=2)
    
    assert view.prev_page.disabled is True
    assert view.next_page.disabled is False
    
    embed = view.get_embed()
    assert "Song Alpha" in embed.description
    assert "Song Beta" in embed.description
    assert "Song Gamma" not in embed.description
    assert embed.footer.text == "Total Songs: 3"
The 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:
pytest
To run a single specific test:
pytest test_bot.py::test_skip_command_playing
To run all tests in the file with verbose output:
pytest test_bot.py -v

Watchdog Mode (Development)

Run ptw in a separate terminal while you work. It monitors all Python files in the project and re-runs the full test suite the moment you save a change, giving you continuous pass/fail feedback without switching windows.
ptw
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):
ptw .

Build docs developers (and LLMs) love