Source code for src.testing.testcases
"""Pytest fixtures for tenant-aware test lifecycle.
Replaces Django's TestCase with pytest fixtures that handle tenant schema
creation, activation, and teardown automatically.
Usage::
# In your conftest.py
from src.testing import tenant_fixture, tenant_context_fixture
# In your test
def test_invoice_creation(tenant_context_fixture):
invoice = Invoice.objects.create(number="INV-001")
assert invoice.tenant_id == tenant_context_fixture.id
"""
from __future__ import annotations
from collections.abc import Generator
from typing import Any
import pytest
[docs]
@pytest.fixture(scope="session")
def tenant_fixture(django_db_setup: Any, django_db_blocker: Any) -> Generator[Any, None, None]:
"""Session-scoped fixture: creates a test tenant with provisioned storage.
The tenant is created once per session and reused across all tests.
Destroys the tenant and its storage after the session ends.
"""
from src.testing.helpers import create_test_tenant, drop_test_tenant
with django_db_blocker.unblock():
tenant = create_test_tenant("test-tenant")
yield tenant
drop_test_tenant(tenant)
[docs]
@pytest.fixture()
def tenant_context_fixture(
tenant_fixture: Any, db: Any,
) -> Generator[Any, None, None]:
"""Function-scoped fixture: activates the tenant context for a single test.
Sets contextvars and activates the isolation backend so all DB operations
target the test tenant's storage. Restores the previous state on teardown.
"""
from django.db import connection
from src.share_kernel.infrastructure.context import current_tenant_var
from src.share_kernel.infrastructure.isolation import get_isolation_backend
backend = get_isolation_backend()
backend.activate_tenant(tenant_fixture, connection)
token = current_tenant_var.set(tenant_fixture)
yield tenant_fixture
backend.deactivate_tenant(connection)
current_tenant_var.reset(token)
[docs]
@pytest.fixture()
def tenant_tx_context_fixture(
tenant_fixture: Any, transactional_db: Any,
) -> Generator[Any, None, None]:
"""Function-scoped fixture for tests requiring real transaction commits.
Same as ``tenant_context_fixture`` but uses ``transactional_db``
instead of ``db``, allowing tests to commit and observe side effects.
"""
from django.db import connection
from src.share_kernel.infrastructure.context import current_tenant_var
from src.share_kernel.infrastructure.isolation import get_isolation_backend
backend = get_isolation_backend()
backend.activate_tenant(tenant_fixture, connection)
token = current_tenant_var.set(tenant_fixture)
yield tenant_fixture
backend.deactivate_tenant(connection)
current_tenant_var.reset(token)