quadkit-testing
Test harnesses, fakes, and fixtures for Quadkit applications: boot the real application in-process, substitute bindings instead of mocking import sites, and assert on responses with helpers that say what failed.
For anyone writing tests against Quadkit applications — and for tooling that needs drop-in implementations of the framework's protocols.
Installation
uv add --dev quadkit-testing
Requires Python >= 3.11.
Minimal working example
Test an HTTP route with the real application, in-process:
import pytest
from quadkit.testing import WebTestBed
from my_app import create_app
@pytest.mark.asyncio
async def test_hello() -> None:
async with WebTestBed(create_app()) as bed:
response = bed.get("/hello", params={"name": "quadkit"})
response.assert_status(200)
assert response.json == {"message": "hello, quadkit"}
Or test services directly, with binding overrides:
async def test_service() -> None:
from quadkit.testing import AppTestBed
async with AppTestBed.from_factory(
create_app, overrides={Cache: FakeCache()}
) as bed:
service = await bed.app.container.resolve(UserService)
A pytest plugin registers automatically via entry points — no
conftest.py wiring — and provides auto-registered fixtures including
fake_cache, fake_event_bus, fake_logger, fake_clock,
fake_command_bus, fake_query_bus, fake_unit_of_work,
fake_metrics, fake_config, fake_state_store, test_bed,
test_container, and test_data.
Optional extras
Verified against the package's pyproject.toml:
| Extra | Contents |
|---|---|
[web] |
httpx + Starlette — the WebTestBed client transport |
[db] |
aiosqlite, asyncpg — drivers for your async DB test suites |
[integration] |
service clients for integration suites (Redis, MongoDB, Kafka, Elasticsearch, Neo4j, Qdrant, PostgreSQL, SQLite) |
[dev] |
ruff, mypy, black |
Public API entry points
Test beds
from quadkit.testing import AppTestBed, WebTestBed
AppTestBed.from_factory(factory, overrides=None)/AppTestBed.from_app(app)— application-level beds.WebTestBed(app_or_provider, raise_server_exceptions=True)withget/post/put/patch/delete,override(Contract, impl)(before boot), andTestResponse—status_code,headers,text,json(property),assert_status,assert_json,assert_json_path,assert_header.quadkit.testing.fixtures.container.ContainerTestFixture— DI-level fixture withmock(),override(),get(),get_optional().quadkit.testing.fixtures.bed.TestEnvironment— programmatic environment builder (use_provider,override,fake,resolve).quadkit.testing.lib.factory.TestDataFactory— deterministiccreate_user(),create_task(),create_message(),create_request().
Fakes (quadkit.testing.fakes)
All in-process, async-native, implementing the same contracts as the real services:
| Class | Covers |
|---|---|
FakeCache / FakeStateStore |
cache and state storage |
FakeEventBus |
in-process events with assert_published(), published_of_type(), assert_events_in_order() and friends |
FakeCommandBus / FakeQueryBus |
command / query dispatch |
FakeUnitOfWork |
unit-of-work context |
FakeClock (+ Clock, SystemClock) |
deterministic time |
FakeConfig |
config overrides |
FakeLogger (+ LogEntry) |
structlog-compatible sink |
FakeMetricsCollector / FakeResourceUnitTracker |
metrics / resource tracking |
FakeRedisClient |
Redis-protocol client |
FakeAuditLogger |
audit records |
FakeTracer / FakeSpan |
tracing |
Fakes that depend on packages outside the published set are not included in this distribution.
Configuration
None required — the pytest plugin self-registers. Mark suites for
external services and gate them yourself (e.g.
uv run pytest -m "not integration").
Error handling
Test beds surface failures, they don't hide them: with
raise_server_exceptions=True (the default) unexpected exceptions
re-raise into your test with their original traceback; HTTP-expected
failures assert on the response instead.
Testing
Ironically self-hosted: this package's public tests are among the suite the release executes from the exported tree against the built wheels.
Security
Fakes are in-process and safe to wire into unit suites. Report vulnerabilities privately per SECURITY.md.
Stability
Version 0.0.3 in the 0.x series, released in lockstep with the
other four distributions; APIs may change between minor versions until
1.0 — pin an exact version (quadkit-testing==0.0.3) or a tight range
(>=0.0.3,<0.1.0). Full policy:
stability and compatibility.
Release files for quadkit-testing 0.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| quadkit_testing-0.0.3.tar.gz | 179.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| quadkit_testing-0.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 341.7 kB
Release files / quadkit_testing-0.0.3.tar.gz
| Download URL | quadkit_testing-0.0.3.tar.gz |
|---|---|
| Size | 179.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
127d3e40457ef9a2dbf163476114c055b02faf6f31cc3ca0f7698482bbfb4881
|
|
BLAKE2b-256 checksum How to use checksums |
e50e13734a6c66b41d07b52f111f45ec4038ef2dce68c13325c8fb4043b489a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.14
|
Release files / quadkit_testing-0.0.3-py3-none-any.whl
| Download URL | quadkit_testing-0.0.3-py3-none-any.whl |
|---|---|
| Size | 161.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
670707536c7c6c6a5cd2593254659b9d66d3b8a8ea1552ffe79a4a193f989603
|
|
BLAKE2b-256 checksum How to use checksums |
618ec46c6ddee90525e7abd6ab73a6fbfd1e2054d15f917d0cdb309640131f68
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.14
|