Files
coding-agent-rules/testing.md
2025-10-04 16:16:05 -04:00

4.2 KiB
Raw Permalink Blame History

trigger
trigger
always_on

General Principles

  • Write unit tests for new features prior to implementing the feature.
  • Write unit tests for utilities and components.
  • Maintain 100% test coverage (backend). Frontend coverage threshold follows CI config (≥90% or 100% for symmetry).
  • Unit tests should never make external calls. Integration tests may call externals.
  • Minimize fixtures for generating inputs; prefer explicit inline inputs/expectations.
  • Tests should be written as functions (avoid class-based tests).
  • Use descriptive, intention-revealing names (e.g., isCreated, hasError) and prefer iteration/modularization over duplication.

Test Structure

Top-level Layout

  • tests/unit/ for pure unit tests (no external I/O).
  • tests/integration/ for tests allowed to hit external services.

Granular Python Unit Test Organization

  1. Use a directory per module under test (e.g., tests/unit/app/services/estimating/).
  2. Within that directory, use a file per function under test (e.g., test_calculate_estimate.py).
  3. Keep unit and integration tests in separate trees: tests/unit/ and tests/integration/.

Naming and Scope

  • Only test functionality in the module under test; dont re-test validation or logic implemented elsewhere.
  • Do not introduce coverage-only test files (e.g., files named with “additional_coverage”, “remaining_branches”, “misc_coverage”).
  • When adding a new test file, name it by feature or unit under test (e.g., test_service_delete_update.py).

Backend (FastAPI) Testing

Framework

  • Pytest

Coverage and Practices

  • Prefer tests over no-cover.
  • Avoid # pragma: no cover except in strictly justified cases:
    • Optional dependency branches or platform guards
    • Defensive/unreachable paths in supported environments
  • Use pytest-mocks mocker fixture for mocking.
  • Use monkeypatches to control time.sleep, random.random, etc., to keep tests fast/deterministic.
  • For network-like behavior, write light fakes with only the attributes used by the code under test.
  • If a safety guard exists (e.g., a best-effort close()), add a micro-test to exercise it.

Commands

  • Full suite (CI-like): bash scripts/ci/backend-test.sh
  • Ad-hoc (from backend/):
    • All tests (with dev extras): uv run --with .[dev] -m pytest
    • With coverage: uv run --with .[dev] -m pytest --cov=app --cov-report=term-missing
    • Single test/file: uv run --with .[dev] -m pytest app/tests/unit/path/to/test_file.py::test_case

Notes

  • Dev extras defined under [project.optional-dependencies].dev in backend/pyproject.toml and include pytest, pytest-cov.
  • Pytest config lives under [tool.pytest.ini_options] in backend/pyproject.toml (e.g., testpaths = ["app/tests"]).
  • Quick run without extras (no coverage): uv run -m pytest (no pytest-cov).

Frontend (React or React Native) Testing

Framework

  • Jest + Testing Library (React) or Jest + React Native Testing Library (React Native)

Mocking Guidance

  • Avoid mocking React/React Native primitives unless necessary.
  • Mock network via MSW.

Commands

  • Full suite (CI-like): bash scripts/ci/frontend-test.sh
  • Ad-hoc (from frontend/):
    • npm: npm run lint then npm test -- --coverage
    • pnpm: pnpm run lint then pnpm test -- --coverage

End-to-End (E2E) Testing

  • Implement E2E tests for critical flows.
  • Choose an appropriate framework based on the frontend:
    • Web (React): Playwright or Cypress
    • React Native: Detox
  • Keep E2E focused on user-critical paths; avoid duplicating unit/integration coverage.

CI Expectations and Consistency

  • CI runs from .gitea/workflows/.
  • Required checks:
    • Backend: ruff, mypy, tests with coverage ≥100%.
    • Frontend: eslint, jest with coverage thresholds (≥90% or 100% for symmetry).
  • No merges to main without green pipelines.
  • Use scripts/ci/* to mirror CI logic locally.

Development Phase Testing (Pre-deployment)

  • Update tests in the same PR when API contracts change (request/response shapes, validation, or status codes).
  • Refresh example payloads in schemas and test fixtures together to prevent drift.
  • Prefer targeted API integration tests for critical endpoints to validate schema and docs alignment.