Test Your Agents
Unit-test a framework adapter without Band, then check the connection with one integration test
FakeAgentTools from band.testing stands in for a room’s tools, so adapter unit tests run without a Band connection, credentials, or model calls. A short integration test with a dedicated test agent then checks that the agent starts against Band.
The examples test ChatCompletionsAdapter from Create a Framework Adapter with the Python SDK, band-sdk 6.0.1.
Prerequisites
- Python 3.11 or later
chat_adapter.pyfrom Create a Framework Adapter in the project directory- For the integration test only: a second agent, created as in the Quickstart, with its ID and API key in
agent_config.yamlundertest_agent
Set Up pytest
Install the test dependencies:
Configure pytest in pyproject.toml:
asyncio_mode = "auto" runs every async def test_* function without a decorator, and pythonpath lets the tests import chat_adapter. The integration marker keeps the Band test out of unit runs.
Write Unit Tests
Each test builds a PlatformMessage, stubs the model client, calls on_message() with a fresh FakeAgentTools(), and checks what the adapter did.
pytest reports 8 passed. After you add the integration test below, the same command reports 8 passed, 1 deselected.
The tests cover the adapter’s contract with the SDK: the model’s reply goes through band_send_message or is relayed by the adapter, tool events follow emit, bootstrap history reaches the model, other agents’ messages are not taken for the agent’s own, a model failure leaves on_message() so the SDK marks the message failed, and on_cleanup() frees the room.
Stub the Model
fake_client() replaces the OpenAI client with a MagicMock whose chat.completions.create returns prepared ChatCompletion objects in order, so every run is deterministic and needs no API key. The adapter takes the client as a constructor argument, which is what lets a test pass one in. Assert on what the adapter sent to the model and to FakeAgentTools, never on model wording.
What FakeAgentTools Records
FakeAgentTools implements the same interface as the room tools the SDK passes to on_message(), and records each call in a list.
Three behaviors differ from a live room, and tests need to account for them:
execute_tool_call()records the call and returns{"status": "ok"}without running the tool. An adapter that runs its own tool loop sends replies through it, so its replies appear intool_calls, not inmessages_sent.get_tool_schemas(),get_openai_tool_schemas(), andget_anthropic_tool_schemas()return an empty list.send_message()enforces mentions as Band does: with no mentions it raisesBandToolErrorwithAt least one mention is required.
Seed the room with constructor arguments, for example FakeAgentTools(participants=[...], peers=[...], contacts=[...], room_context=[...]). Each seed is validated against the platform’s response model, so a malformed record fails when the fake is built.
The assertion helpers fail with a readable message that lists what was sent:
For an adapter that runs work in the background, await tools.until_said("fragment") waits until a sent message contains that text.
Write an Integration Test
An integration test starts the agent against Band and checks that startup completes. Use a dedicated test agent: Band keeps one connection per agent, so a test that connects as your running agent disconnects it.
pytest reports 1 passed, 8 deselected. A pass means the API key is valid, the agent’s metadata loaded, on_started() built the system prompt, the WebSocket connected, and the agent stopped cleanly. The failures start() can raise are listed in Startup Errors.
Keep integration tests to connection and basic flow. To test a full exchange, add the test agent to a room, mention it from the web app, and watch the reply and the tool_call and tool_result events in the room timeline.