Skip to main content
Motus uses pytest with three test tiers: unit, integration (VCR replay), and slow (live API).

Running tests

Test markers

Run a specific marker:

VCR cassette system

VCR cassettes record and replay HTTP interactions so integration tests run without live API access. This is the primary mechanism for testing agent behavior end-to-end.

Where cassettes live

Each cassette is a YAML file containing the recorded request/response pairs.

Replay mode (default, CI)

No API keys needed. The _fake_api_keys fixture injects placeholder keys so the HTTP client constructs valid-looking requests, and VCR intercepts them before they reach the network.

Record mode

To record new cassettes or re-record existing ones, run with real API keys set in your environment:
Cassettes are automatically scrubbed of:
  • API keys and authorization headers
  • Base64-encoded binary blobs
  • OpenAI reasoning content
A custom JSON body matcher normalizes whitespace for stable matching across recording sessions.

When to record

  • You add a new integration test that makes HTTP calls
  • An upstream API changes its response format
  • You modify agent behavior that changes the request sequence

Async tests

asyncio_mode = "auto" is set in pyproject.toml. All async def test_* functions run automatically without the @pytest.mark.asyncio decorator.
For class-based async tests, inherit from unittest.IsolatedAsyncioTestCase:

Writing a new test

Follow this checklist:
  • Place unit tests in tests/unit/<module>/ mirroring the src/motus/ structure.
  • Place integration tests in tests/integration/.
  • If your test makes HTTP calls, record a VCR cassette and commit it with your PR.
  • If your test uses the runtime, call shutdown() in teardown to avoid leaked tasks.
  • Name test files with the test_ prefix (e.g., test_agent_task.py).
  • Name test functions with the test_ prefix describing the behavior under test.

Coverage

You can generate a coverage report locally:
Focus coverage on the code you changed. Full-repo coverage targets are not enforced, but reviewers may ask for tests if you add untested code paths.