Shared Python testing utilities for Thenvoi repositories - fixtures, factories, and fakes
Project description
thenvoi-testing-python
Shared Python testing utilities for Thenvoi repositories. Provides fixtures, factories, and fakes for testing adapters, WebSocket clients, and API integrations.
Installation
Install from GitHub using uv:
# Core package
uv add "thenvoi-testing-python @ git+https://github.com/thenvoi/thenvoi-testing-python.git"
# With WebSocket testing support
uv add "thenvoi-testing-python[websocket] @ git+https://github.com/thenvoi/thenvoi-testing-python.git"
# With REST client testing support
uv add "thenvoi-testing-python[rest] @ git+https://github.com/thenvoi/thenvoi-testing-python.git"
# Full installation
uv add "thenvoi-testing-python[full] @ git+https://github.com/thenvoi/thenvoi-testing-python.git"
Quick Start
The package automatically registers pytest fixtures when installed. Just use them in your tests:
# Tests automatically have access to fixtures
async def test_adapter_sends_message(fake_agent_tools):
adapter = MyAdapter()
await adapter.process(message, fake_agent_tools)
assert len(fake_agent_tools.messages_sent) == 1
assert fake_agent_tools.messages_sent[0]["content"] == "Hello!"
def test_with_factory(factory):
agent = factory.agent_me(id="test-123", name="TestBot")
response = factory.response(agent)
assert response.data.id == "test-123"
Components
Factories
Mock data factories for creating test objects that behave like Pydantic models:
from thenvoi_testing.factories import factory
# Create mock objects with OpenAPI example defaults
agent = factory.agent_me()
agent = factory.agent_me(id="custom-id", name="CustomBot")
# Create response wrappers
response = factory.response(agent)
list_response = factory.list_response([room1, room2])
# Available factory methods:
# - agent_me() - AgentMe object
# - peer() - Peer object
# - chat_room() - ChatRoom object
# - chat_participant() - ChatParticipant object
# - chat_message() - ChatMessage object
# - chat_event() - ChatEvent object
# - user_profile() - UserProfile object
# - owned_agent() - OwnedAgent object
# - registered_agent() - RegisteredAgent (with credentials)
# - deleted_agent() - DeletedAgent object
Fakes
Fake implementations for testing without mocking frameworks:
from thenvoi_testing.fakes import FakeAgentTools
# FakeAgentTools tracks all tool calls
tools = FakeAgentTools()
await tools.send_message("Hello!")
await tools.send_event("Processing", "thought")
await tools.add_participant("Alice")
# Assert on tracked calls
assert len(tools.messages_sent) == 1
assert tools.messages_sent[0]["content"] == "Hello!"
assert len(tools.events_sent) == 1
assert len(tools.participants_added) == 1
For WebSocket testing (requires websocket extra):
from thenvoi_testing.fakes import FakePhoenixServer
@pytest_asyncio.fixture
async def phoenix_server():
server = FakePhoenixServer()
await server.start()
try:
yield server
finally:
await server.stop()
async def test_websocket(phoenix_server):
async with PHXChannelsClient(phoenix_server.url) as client:
await client.subscribe_to_topic("test-topic", callback)
await phoenix_server.simulate_server_event(
"test-topic", "new_message", {"text": "hello"}
)
Markers
Skip markers for conditional test execution:
from thenvoi_testing.markers import (
skip_without_env,
skip_without_envs,
skip_with_condition,
skip_in_ci,
pytest_ignore_collect_in_ci,
)
# Skip if environment variable not set
requires_api = skip_without_env("THENVOI_API_KEY")
@requires_api
def test_api_call():
...
# Skip if any of multiple env vars not set
requires_multi_agent = skip_without_envs(
["THENVOI_API_KEY", "THENVOI_API_KEY_2"],
reason="Both API keys required"
)
# Skip in CI environment
@skip_in_ci
def test_local_only():
...
# In conftest.py - skip integration folder in CI
def pytest_ignore_collect(collection_path):
return pytest_ignore_collect_in_ci(str(collection_path), "integration")
Event Factories
Create WebSocket event objects for testing handlers:
from thenvoi_testing.factories.events import (
make_message_event,
make_room_added_event,
make_participant_added_event,
)
# Create a message event with defaults
event = make_message_event()
assert event.type == "message_created"
assert event.payload.sender_type == "User"
# Create with custom values
event = make_message_event(
room_id="room-123",
content="Hello!",
sender_id="user-456",
sender_type="Agent",
)
Pagination Helpers
Utilities for integration tests against paginated APIs:
from thenvoi_testing.pagination import (
fetch_all_pages,
find_item_in_pages,
item_exists_in_pages,
)
# Fetch all items from paginated endpoint
all_peers = fetch_all_pages(ctx, list_agent_peers)
# Find specific item with predicate
room = find_item_in_pages(
ctx, list_agent_chats,
lambda item: item.get("title") == "My Room"
)
# Check if item exists
if item_exists_in_pages(ctx, list_agent_chats, room_id):
print("Room exists!")
Settings
Base settings class for integration tests using Pydantic Settings:
from pathlib import Path
from thenvoi_testing.settings import ThenvoiTestSettings
class TestSettings(ThenvoiTestSettings):
_env_file_path = Path(__file__).parent / ".env.test"
settings = TestSettings()
# Check if credentials are available
if settings.has_api_key:
client = create_client(settings.thenvoi_api_key)
if settings.has_multi_agent:
# Both agents available for multi-agent tests
pass
Example .env.test:
THENVOI_API_KEY=your-agent-api-key
TEST_AGENT_ID=your-agent-uuid
THENVOI_API_KEY_2=second-agent-key
TEST_AGENT_ID_2=second-agent-uuid
THENVOI_API_KEY_USER=user-api-key
THENVOI_BASE_URL=https://api.thenvoi.com
THENVOI_WS_URL=wss://api.thenvoi.com/api/v1/socket/websocket
Pytest Plugin
The package registers as a pytest plugin automatically. Available fixtures:
| Fixture | Description |
|---|---|
fake_agent_tools |
Fresh FakeAgentTools instance |
mock_websocket |
AsyncMock WebSocket client |
factory |
MockDataFactory instance |
mock_agent_api |
MagicMock of agent_api namespace |
mock_human_api |
MagicMock of human_api namespace |
mock_api_client |
AsyncMock with both APIs attached |
api_client |
Real RestClient for integration tests (requires rest extra) |
sample_room_message |
MessageCreatedPayload from a user |
sample_agent_message |
MessageCreatedPayload from an agent |
Integration Testing with api_client
The api_client fixture provides a real REST client for integration tests:
def test_integration(api_client):
if api_client is None:
pytest.skip("THENVOI_API_KEY not configured")
response = api_client.agent_api.get_agent_me()
assert response.data.id is not None
It uses ThenvoiTestSettings to load configuration from environment variables.
Development
# Clone the repository
git clone git@github.com:thenvoi/thenvoi-testing-python.git
cd thenvoi-testing-python
# Install with dev dependencies
uv sync --extra dev
# Run tests
uv run pytest tests/ -v
# Run linting
uv run ruff check .
uv run ruff format .
Branching & Releases
This repository uses a main-only branch strategy:
- Branch:
main(nodevbranch) - Versioning: Git tags (e.g.,
v0.1.0,v0.2.0) - Workflow: Feature branch → PR → squash merge to
main→ tag release
To pin to a specific version:
uv add "thenvoi-testing-python @ git+https://github.com/thenvoi/thenvoi-testing-python.git@v0.1.0"
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file band_testing_python-0.1.3.tar.gz.
File metadata
- Download URL: band_testing_python-0.1.3.tar.gz
- Upload date:
- Size: 61.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f92f21d552e427b8773ea432100af7124c0ced012749441ea0454f92f5e6ddf
|
|
| MD5 |
a7448836116f21370a8c24c08daf21f3
|
|
| BLAKE2b-256 |
3d25d217d294e88499dcb3eeba0ebe31431d18aab1dfe41a3ae709a4efe1ccda
|
Provenance
The following attestation bundles were made for band_testing_python-0.1.3.tar.gz:
Publisher:
release.yml on thenvoi/thenvoi-testing-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
band_testing_python-0.1.3.tar.gz -
Subject digest:
2f92f21d552e427b8773ea432100af7124c0ced012749441ea0454f92f5e6ddf - Sigstore transparency entry: 1280750797
- Sigstore integration time:
-
Permalink:
thenvoi/thenvoi-testing-python@0fd261a0b7bd4aa4ea1a5ef485c7867277b63086 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/thenvoi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0fd261a0b7bd4aa4ea1a5ef485c7867277b63086 -
Trigger Event:
push
-
Statement type:
File details
Details for the file band_testing_python-0.1.3-py3-none-any.whl.
File metadata
- Download URL: band_testing_python-0.1.3-py3-none-any.whl
- Upload date:
- Size: 25.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
871e16b9113945126e263fb44b14ec27e6c8076b40d80e8a551865db37df3cf4
|
|
| MD5 |
17a0730501d6fea821cf231dfdfbee97
|
|
| BLAKE2b-256 |
e1b38cd4e2951c8c82f24bfa87077eb7c3ae0d4cbe88dc1ba75ebc0229c32d8d
|
Provenance
The following attestation bundles were made for band_testing_python-0.1.3-py3-none-any.whl:
Publisher:
release.yml on thenvoi/thenvoi-testing-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
band_testing_python-0.1.3-py3-none-any.whl -
Subject digest:
871e16b9113945126e263fb44b14ec27e6c8076b40d80e8a551865db37df3cf4 - Sigstore transparency entry: 1280750799
- Sigstore integration time:
-
Permalink:
thenvoi/thenvoi-testing-python@0fd261a0b7bd4aa4ea1a5ef485c7867277b63086 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/thenvoi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0fd261a0b7bd4aa4ea1a5ef485c7867277b63086 -
Trigger Event:
push
-
Statement type: