Files
aurum/backend/tests
technosexual 76c5caa667 fix: actually reject zero-amount goal contributions (#4)
`GoalContributionCreate.amount` used `Field(ne=0)`, but pydantic has no
"not equal" constraint — the keyword was accepted as unknown schema
metadata and never validated anything. `POST /api/goals/{id}/contributions`
with `"amount": "0"` returned 201 and wrote a contribution that moves the
goal's progress by nothing, and the comment right above the field says zero
is pointless.

Replaced with a field_validator so the rule is enforced, deliberately not
with `gt=0`: negative contributions are intentional (money taken back out of
a goal), and the added tests pin both halves of that.

This also clears the `PydanticDeprecatedSince20: Using extra keyword
arguments on Field (Extra keys: 'ne')` warning that the test suite printed
on every run — that warning was the symptom.


Claude-Session: https://claude.ai/code/session_01UmuMDFrwdvQkce885VaaTh

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 02:43:11 +03:00
..

Backend tests

Real integration tests against a real Postgres database — a dedicated aurum_test database created fresh, migrated, and dropped again on every run. They never touch the real aurum database or its data: the app's lifespan startup (which seeds against the real DB) is never triggered, and every route's DB dependency is overridden to point at aurum_test instead.

Running

The stack must already be up (docker compose up -d). Test dependencies aren't baked into the production image, so install them once per container lifetime, then run pytest inside the running backend container — it's the only place with network access to Postgres:

docker compose exec backend pip install -r requirements-dev.txt
docker compose exec backend pytest -v

Re-run just pytest -v for subsequent runs; the pip install only needs repeating after a container restart/rebuild.

Adding a test

  • Use the client fixture (an httpx.AsyncClient wired to the app) to hit the API the same way the frontend does — prefer this over reaching into services/models directly, so tests keep verifying the actual contract.
  • account_id and categories fixtures give you the same default account/categories a real fresh install seeds.
  • Every table is truncated and reseeded before each test (see conftest.py::_clean_database), so tests don't need to worry about leftover state or guess at IDs from a previous test.