Skip to content

Frequently asked questions

What is SimCord?

SimCord is a testing framework for discord.py bots. It gives your real, unmodified bot a faithful but entirely in-memory Discord to run against, so you can test prefix commands, slash commands, buttons, modals, permissions and events — with no network, no bot token, and no test server. See the overview and quickstart.

Does it connect to Discord? Is it against the Terms of Service?

No, and no. SimCord never opens a socket. It replaces discord.py's two transport seams (the REST client and the gateway parser) with an in-memory backend, so nothing reaches Discord's servers. There is deliberately no "integration mode" — automating a real client would violate Discord's Terms of Service, and this project exists precisely to make that unnecessary. See the architecture.

How is it different from dpytest?

dpytest started this approach. SimCord covers the modern interaction surface dpytest doesn't — slash commands, context menus, components, modals, autocomplete — and enforces real permissions with authentic Discord error codes. It also replaces dpytest's module-global API with explicit builders and actors, so messages are sent by someone, from somewhere, which is what makes permission-sensitive bugs testable. There's a full migration guide.

Is this a mock library?

It's more than a mock — it's a simulator. A mock returns canned responses; SimCord maintains real, consistent state. When your bot sends a message, the same backend produces both the REST response and the MESSAGE_CREATE gateway event, so your bot's cache and listeners behave exactly as in production. Permissions, the interaction lifecycle and validation limits are all computed, not faked.

Do I have to change my bot to test it?

No. SimCord runs your real, unmodified bot. The only requirement is that you can construct it from a function (so tests can build a fresh instance) — see the quickstart. Your setup_hook, extension loading and tree.sync() all run for real.

Why do my async tests need no decorator?

The pytest extra installs pytest-asyncio. With asyncio_mode = "auto" set in your pyproject.toml, async def test_... functions run automatically. See Fixtures & configuration.

Do I need asyncio.sleep to wait for the bot to reply?

No — and you shouldn't. Every actor verb waits for the bot to finish reacting before returning, so your assertions never race. SimCord tracks the bot's tasks and settles the event loop deterministically. If you need to advance time (for cooldowns or view timeouts), use env.advance_time, not a real sleep.

My test fails saying a command "was never synced". Why?

Because SimCord enforces sync, just like Discord: a command in your tree that you never tree.sync()'d can't be invoked. This catches a very common real bug. Make sure your setup_hook syncs, or pass strict_sync=False for isolated unit tests.

A test passes but I expected the bot to error?

By default, errors your bot raised but never inspected are re-raised at teardown. If you expect errors, read env.errors (which marks them inspected) and assert on them; if you want to assert the bot ran clean, call env.raise_errors().

What happens if my bot hits something SimCord doesn't support yet?

It raises RouteNotImplemented naming the exact route — never a silent fake success. Check the parity matrix for what's implemented, and open a parity-gap issue for what you need.

Does SimCord simulate sharding or rate limits?

No — both are deliberately out of scope. A test drives a single virtual shard, and skipping rate limits keeps tests fast; use inject_error to exercise your 429 handling. See the parity matrix.

Which Python and discord.py versions are supported?

Python 3.11+ and discord.py 2.7+. See Installation.

Still stuck?