Skip to content

Document resource extension workflow and centralize API test helpers #47

Description

@Subhransu-De

What to build

Make the template easier to extend with another CRUD resource by documenting the concrete code paths that must be updated and by moving repeated API-test assertions into shared test utilities.

This is related to #25, but it is narrower: the focus here is resource extension, test reuse, integration-test prerequisites, and local command portability.

Verified repository evidence

  • The only full resource slice is Entity, spread across:
    • app/model/entity.py
    • app/io/entity.py
    • app/repository/entity.py
    • app/service/entity.py
    • app/routes/entity.py
    • tests/unit/io/test_entity.py
    • tests/unit/service/test_entity_service_behaviour.py
    • tests/integration/test_entities_api.py
  • Resource registration is split across several files:
    • app/model/__init__.py imports and exports Entity.
    • alembic/env.py uses Base.metadata as Alembic target_metadata, so new SQLAlchemy models need to be imported into the model package before autogeneration can see them.
    • app/io/__init__.py re-exports entity schemas.
    • app/repository/__init__.py re-exports EntityRepository.
    • app/service/__init__.py defines service_dependency(...), creates get_entity_service, and exports both EntityService and get_entity_service.
    • app/routes/__init__.py mounts health_route on public_route and entity_route on auth-protected protected_route.
    • app/exceptions/__init__.py re-exports NoEntityFoundError.
  • Protected integration tests rely on a marker:
    • tests/integration/conftest.py defines WithAuth = pytest.mark.with_auth.
    • The app_client fixture only injects the Bearer token when the current test has the with_auth marker.
    • tests/integration/test_entities_api.py uses @WithAuth for protected entity API tests.
  • Integration tests require Docker/Testcontainers:
    • tests/integration/conftest.py starts PostgresContainer(image="postgres:18-alpine", ...).
    • pyproject.toml documents the integration marker, but README only shows make test and make test-cov.
  • API response assertion helpers are local to tests/integration/test_entities_api.py:
    • _assert_problem_details(...)
    • _assert_validation_problem(...)
    • _assert_unauthorized(...)
  • Unit-test fixtures are inconsistent:
    • tests/unit/conftest.py provides mock_session and mock_entity_repository.
    • tests/unit/service/test_entity_service_behaviour.py defines local session and repository fixtures instead of using the shared fixture pattern.
  • The Makefile run target is POSIX-shell-specific:
    • It uses [ ! -f .env ], cp, and backslash continuations.
    • README does not provide PowerShell-friendly equivalents for setup/run/test commands.

Acceptance criteria

  • Add an "Extending the template" section to README or a dedicated repository doc such as CONTRIBUTING.md.
  • Document the vertical-slice checklist for a new CRUD resource, including:
    • SQLAlchemy model file.
    • Import/export in app/model/__init__.py so Alembic metadata includes the model.
    • Alembic migration creation and review.
    • Pydantic request/response schemas and app/io/__init__.py export.
    • Repository wrapper when needed and app/repository/__init__.py export.
    • Service implementation.
    • get_*_service = service_dependency(...) wiring and app/service/__init__.py export.
    • Route module.
    • Router registration in app/routes/__init__.py.
    • Custom exception and app/exceptions/__init__.py export when the resource needs a typed 404 or domain error.
    • Unit tests and integration API tests.
  • Document the routing convention explicitly:
    • Normal authenticated resource routes go through protected_route.
    • Health checks or intentionally unauthenticated endpoints go through public_route.
  • Document local verification commands and prerequisites:
    • uv run --group test pytest -m unit
    • uv run --group test pytest -m integration
    • Docker must be available for integration tests because Testcontainers starts PostgreSQL.
    • Protected-route integration tests need @WithAuth or pytest.mark.with_auth.
    • uv run ruff check .
    • uv run ty check
  • Extract shared API assertion helpers from tests/integration/test_entities_api.py into a reusable test helper module, for example tests/helpers/api_assertions.py or tests/integration/helpers.py.
  • Update existing integration tests to use the shared API assertion helpers without reducing coverage.
  • Consolidate unit fixture usage by either:
    • Reusing the shared mock_session / repository fixture pattern in service tests, or
    • Replacing the entity-specific repository fixture with a generic helper that can be reused by future service tests.
  • Add PowerShell-friendly setup/run/test commands to README or replace the POSIX-specific Makefile run bootstrap with a cross-platform helper script.
  • Keep the existing checks passing after the changes:
    • uv run --group test pytest -m unit
    • uv run --group test pytest -m integration when Docker is running
    • uv run ruff check .
    • uv run ty check

Non-goals

  • Do not add a second public endpoint just for demonstration; the existing health route already exercises the public router path.
  • Do not change authentication behavior for the existing protected entity routes.
  • Do not reduce the current integration coverage for entity CRUD, validation, authorization, pagination, missing records, or telemetry.

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationenhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions