TDD Kit¶
The TDD Kit is the test-runtime infrastructure layer of django-mindoff. It provides deterministic, reusable testing primitives for apps, models, API invocation, and response-contract assertions.
It standardizes test setup so teams can focus on behavior contracts instead of boilerplate environment wiring.
For practical test-writing workflow, see Developer Guide - Test-Driven Development.
Architecture & Intent¶
The kit is built around one mixin surface (MindoffTestCase) plus one router-focused mixin (MindoffRouterTestCase):
MindoffTestCasehandles isolated app/model/runtime setup and API test helpers.MindoffRouterTestCaseenforces version-router dispatch correctness.
This split keeps endpoint-behavior tests and router-behavior tests explicit and reusable.
Core Runtime Components¶
| Component | Responsibility | Examples |
|---|---|---|
MindoffTestCase |
Injected pytest fixtures for app/model mocking, API calls, response assertions, and users. | self.mo_mock_app, self.mo_mock_call_api |
MindoffRouterTestCase |
Reusable assertions for VERSION_MAP routing behavior. |
dispatch and unknown-version checks |
| Dynamic resource helpers | Build and teardown temporary apps/models/tables safely. | _ensure_dynamic_app, _create_model, _cleanup_dynamic_app |
| Frame fixture helpers | Generate and mutate model-backed Polars fixtures. | mo_mock_model_frms, mo_update_mock_model_frms |
Fixture Injection Lifecycle¶
MindoffTestCase.run is an autouse fixture that injects helper surfaces into each test instance:
self.mo_mock_appself.mo_mock_modelself.mo_mock_model_frmsself.mo_update_mock_model_frmsself.mo_mock_call_apiself.mo_assert_api_responseself.mo_mock_userself.assertsself.client(APIClient)
It also resets mo_validation_kit state when available to avoid cross-test aggregate contamination.
Dynamic App & Model Runtime¶
Temporary App Isolation (mo_mock_app)¶
mo_mock_app(...) creates a temporary Django app at runtime and wires it into test execution:
- Creates temp app package and URL modules.
- Inserts temp path into
sys.path. - Applies
override_settingsforINSTALLED_APPSand root URLConf. - Clears app/url caches for resolver consistency.
- Registers teardown that removes modules, path injections, URL cache state, and temp files.
Dynamic Model Engineering (mo_mock_model)¶
mo_mock_model(...) builds runtime model classes and real DB tables:
- Validates naming and FK parameters.
- Resolves current app context or creates isolated dynamic app.
- Generates model class with UUID PK and optional FK/field definitions.
- Creates table via schema editor.
- Registers teardown to drop created tables and cleanup dynamic app state.
This allows integration-style tests against actual ORM tables without permanent project mutations.
Polars Fixture Architecture¶
Model-to-Frame Generation (mo_mock_model_frms)¶
Creates dict[ModelClass, DataFrame] fixtures from bakery-prepared objects:
- Supports per-model row counts.
- Supports per-model excluded columns.
- Supports row-level modifications (
modifymap). - Can enforce DB-column naming.
- Can flatten FK values to ids.
- Supports UUID generation mode controls.
Controlled Frame Mutation (mo_update_mock_model_frms)¶
Updates existing frame fixtures with newly generated values while protecting key relational columns:
- PK and FK columns are always protected.
- User-specified keep columns are merged with protected columns.
- Non-protected columns are replaced with generated fixture values.
- Optional post-update row modifications are applied.
This preserves relational integrity while enabling update-focused test scenarios.
API Invocation Architecture¶
mo_mock_call_api(...) provides URL-name driven API invocation with runtime policy checks:
- Resolves API URL and detects versioned routing.
- Resolves API class and reads configured HTTP
method. - Enforces allowed methods (
get|post|put|patch|delete). - Rejects payload for
GET/DELETE(requires query params instead). - Applies authentication and headers.
- Forces queue-mode APIs into direct execution for deterministic testing.
- Executes request through DRF
APIClient.
This creates one consistent API-call surface across sync and queue-configured endpoints.
Response Contract Assertions¶
mo_assert_api_response(...) is a contract assertion layer for response shape/media expectations:
- Asserts response existence.
- Asserts exact status code.
- Asserts content type by expected response category:
jsonplainhtmlbinaryothers(status-only contract)
This keeps tests aligned with transport-level API contracts, not only payload fragments.
User Fixture Strategy¶
mo_mock_user(...) creates or reuses auth users:
- Reuses existing user when username already exists.
- Creates user with bakery otherwise.
- Sets password when provided.
This makes authenticated test setup stable and repeatable.
Router Verification Layer¶
MindoffRouterTestCase validates version-router behavior:
- Every configured
VERSION_MAPentry dispatches to expected class (as_viewcall path). - Unknown versions return 404 with
INVALID_API_VERSIONandavailable_versionspayload.
This guards version-routing correctness independent of endpoint business logic.
Safety & Cleanup Model¶
The kit aggressively cleans mutable test runtime state:
- URL resolver caches are cleared during setup/teardown.
- Dynamically imported modules are removed from
sys.modules. - Temporary filesystem paths are removed.
- Temporary DB tables are dropped.
- App registry caches are refreshed.
These safeguards reduce flaky behavior from shared global Django runtime state.
Troubleshooting the Kit¶
- Versioned API call fails unexpectedly: ensure
url_kwargsincludesversion. - GET/DELETE test raises payload error: move data into
query_params. - Dynamic app/model leakage between tests: verify test uses provided helpers and allows fixture teardown to run.
- Frame updates break relations: check
keep_columnsand ensure PK/FK columns are not overridden. - Router tests fail for missing version: confirm target version exists in router
VERSION_MAP.