Source code for src.testing.helpers

"""Test helper functions for creating and destroying test tenants and users.

These are standalone functions (not fixtures) that can be called from
fixtures, factory functions, or test setup code.

Usage::

    from src.testing.helpers import create_test_tenant, create_test_user

    tenant = create_test_tenant("acme")
    user = create_test_user("dev@acme.com")
"""

from __future__ import annotations

import logging
from typing import Any

logger = logging.getLogger(__name__)


[docs] def create_test_tenant(slug: str = "test-tenant", name: str | None = None) -> Any: """Create a test tenant with its storage provisioned. If a tenant with the given slug already exists, it is reused. Args: slug: Tenant slug (must be unique). name: Tenant display name (defaults to title-cased slug). Returns: The created or existing Tenant instance. """ from src.module.tenant.models import Tenant from src.share_kernel.infrastructure.isolation import get_isolation_backend tenant, created = Tenant.objects.get_or_create( slug=slug, defaults={ "name": name or slug.replace("-", " ").title(), }, ) if created: backend = get_isolation_backend() backend.create_tenant_storage(tenant) logger.info("Created test tenant: %s", slug) else: logger.info("Reusing existing test tenant: %s", slug) return tenant
[docs] def drop_test_tenant(tenant: Any) -> None: """Destroy a test tenant and its storage. Args: tenant: The Tenant instance to destroy. """ from src.share_kernel.infrastructure.isolation import get_isolation_backend try: backend = get_isolation_backend() backend.destroy_tenant_storage(tenant) tenant.delete() logger.info("Dropped test tenant: %s", tenant.slug) except Exception: logger.exception("Failed to drop test tenant: %s", tenant.slug)
[docs] def create_test_user( email: str = "test@example.com", password: str = "testpass123", **kwargs: Any, ) -> Any: """Create a test user. If a user with the given email already exists, it is reused. Args: email: User email. password: User password. **kwargs: Additional user fields (first_name, last_name, etc.). Returns: The created or existing User instance. """ from django.contrib.auth import get_user_model User = get_user_model() # noqa: N806 user, created = User.objects.get_or_create( email=email, defaults=kwargs, ) if created: user.set_password(password) user.save() return user
[docs] def create_test_membership( user: Any, tenant: Any, roles: list[str] | None = None, abac_attributes: dict[str, Any] | None = None, ) -> Any: """Create a TenantMembership for testing. Args: user: The User instance. tenant: The Tenant instance. roles: List of role names (default: empty list). abac_attributes: ABAC attributes dict (default: empty dict). Returns: The created TenantMembership instance. """ from src.module.tenant.models import TenantMembership return TenantMembership.objects.create( user=user, tenant=tenant, roles=roles or [], abac_attributes=abac_attributes or {}, status="active", )