Metadata-Version: 2.5
Name: quadkit-testing
Version: 0.0.3
Summary: Centralized testing infrastructure for Quadkit Framework - Fixtures, factories, and utilities
Project-URL: Homepage, https://quadkit.dev
Project-URL: Repository, https://github.com/dbtinoy-/quadkit
Project-URL: Documentation, https://quadkit.dev
Project-URL: Issues, https://github.com/dbtinoy-/quadkit/issues
Project-URL: Changelog, https://github.com/dbtinoy-/quadkit/blob/main/CHANGELOG.md
Author-email: Quadkit Framework Team <team@quadkit.dev>
Maintainer-email: Quadkit Framework Team <team@quadkit.dev>
License: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: async,factories,fixtures,framework,mocking,pytest,testing
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Framework :: Pytest
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Testing
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: pytest-asyncio>=0.21.0
Requires-Dist: pytest-cov>=4.0.0
Requires-Dist: pytest-mock>=3.10.0
Requires-Dist: pytest>=8.0.0
Requires-Dist: quadkit-contracts>=0.0.2
Requires-Dist: quadkit>=0.0.2
Provides-Extra: db
Requires-Dist: aiosqlite>=0.19.0; extra == 'db'
Requires-Dist: asyncpg>=0.29.0; extra == 'db'
Provides-Extra: dev
Requires-Dist: black>=23.0.0; extra == 'dev'
Requires-Dist: mypy>=1.0.0; extra == 'dev'
Requires-Dist: ruff>=0.16.4; extra == 'dev'
Provides-Extra: integration
Requires-Dist: aiokafka>=0.12.0; extra == 'integration'
Requires-Dist: aiosqlite>=0.19.0; extra == 'integration'
Requires-Dist: asyncpg>=0.29.0; extra == 'integration'
Requires-Dist: elasticsearch[async]>=8.12.0; extra == 'integration'
Requires-Dist: motor>=3.3.0; extra == 'integration'
Requires-Dist: neo4j>=5.18.0; extra == 'integration'
Requires-Dist: qdrant-client>=1.9.0; extra == 'integration'
Requires-Dist: redis>=5.0.0; extra == 'integration'
Provides-Extra: web
Requires-Dist: httpx2>=2.0.0; extra == 'web'
Requires-Dist: httpx>=0.26.0; extra == 'web'
Requires-Dist: starlette>=0.28.0; extra == 'web'
Description-Content-Type: text/markdown

# 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

```bash
uv add --dev quadkit-testing
```

Requires **Python >= 3.11**.

## Minimal working example

Test an HTTP route with the real application, in-process:

```python
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:

```python
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

```python
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)` with
  `get/post/put/patch/delete`, `override(Contract, impl)` (before
  boot), and `TestResponse` — `status_code`, `headers`, `text`,
  `json` (property), `assert_status`, `assert_json`,
  `assert_json_path`, `assert_header`.
- `quadkit.testing.fixtures.container.ContainerTestFixture` — DI-level
  fixture with `mock()`, `override()`, `get()`, `get_optional()`.
- `quadkit.testing.fixtures.bed.TestEnvironment` — programmatic
  environment builder (`use_provider`, `override`, `fake`, `resolve`).
- `quadkit.testing.lib.factory.TestDataFactory` — deterministic
  `create_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](../../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](../../docs/reference/stability.md).

Issues: <https://github.com/dbtinoy-/quadkit/issues>
