Agents work on this repository in the agent-envs sandbox: a container whose only way out is an egress proxy with an allowlist, which also adds the Gitea bot token. docs/contributing/agents.md covers setting it up for Politrack (1Password item, .env, commit identity), what it can reach and its limits; AGENTS.md tells agents how to recognise the sandbox and behave in it. backend/tests/Dockerfile.debian gains a `sandbox` target: the agent-envs agent image plus the backend's dependencies from Debian packages, the same list as the PyPI-free test image (still the default target). The sandbox runs `pytest` without PyPI, which the owner's PC can't reach. A new invariant in AGENTS.md keeps that list in step with pyproject.toml. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
69 lines
3.0 KiB
Markdown
69 lines
3.0 KiB
Markdown
# Testing
|
|
|
|
```bash
|
|
cd backend
|
|
pytest # everything below except the DB smoke test
|
|
pytest tests/test_golden.py -k parlament # one adapter's golden tests
|
|
UPDATE_GOLDEN=1 pytest tests/test_golden.py # regenerate expected outputs (review the diff!)
|
|
```
|
|
|
|
| suite | what it covers | needs |
|
|
|---|---|---|
|
|
| `tests/test_core.py` | framework invariants: request identity, secret redaction, registry consistency, record serialisation, OpenAPI→TS generator, shared helpers | nothing |
|
|
| `tests/test_parsers.py` | parsing helpers (vote texts, CSV layouts of the Rechnungshof, dates, normalisation) | nothing |
|
|
| `tests/test_extraction.py` | roll-call lists, immunity reports, event/legal/office-title detection | nothing |
|
|
| `tests/test_golden.py` | every captured fixture replayed through `adapter.parse()` and compared with `<case>.expected.json` | nothing |
|
|
|
|
Parsers are pure, so none of these needs a database or network.
|
|
|
|
### Without PyPI access
|
|
|
|
`tests/Dockerfile.debian` installs the dependencies from Debian packages instead (everything except
|
|
`procrastinate` and `mcp`, which the tests don't need):
|
|
|
|
```bash
|
|
docker build -t politrack-test -f backend/tests/Dockerfile.debian backend/tests
|
|
docker run --rm -v "$PWD/backend:/app" politrack-test python3 -m pytest -q -p no:cacheprovider
|
|
```
|
|
|
|
The test image can also run adapters against the compose database: add
|
|
`--network politics-tracking_default` and
|
|
`-e POLITRACK_DATABASE_URL=postgresql://politrack:<password>@db:5432/politrack`, then
|
|
`python3 -m politrack.cli run <adapter> --max-requests 20`.
|
|
|
|
The same package list builds the agent sandbox image (target `sandbox`, see
|
|
[agents.md](agents.md#the-sandbox-image)), so keep it in step with `pyproject.toml`.
|
|
|
|
## Golden fixtures
|
|
|
|
```
|
|
tests/fixtures/<adapter name>/<case>.request.json {url, kind, meta, content_type, body_file}
|
|
tests/fixtures/<adapter name>/<case>.<ext> the captured body
|
|
tests/fixtures/<adapter name>/<case>.expected.json parse() output (records as JSON)
|
|
```
|
|
|
|
Capture with `politrack fixture <adapter> <url> <case> --kind <kind> --meta '{"…": …}'`. A fixture
|
|
without `.expected.json` creates it on the first run and is skipped until you have reviewed it.
|
|
|
|
When a source changes its format: capture a new case next to the old one (keep the old one if the
|
|
publisher still serves old documents in that format), fix the parser, bump `parser_version`.
|
|
|
|
## Against a real database
|
|
|
|
The quickest end-to-end check uses the compose stack:
|
|
|
|
```bash
|
|
docker compose up -d db && docker compose run --rm migrate
|
|
docker compose run --rm api politrack run parlament.persons --max-requests 20 -p periods='["XXVIII"]'
|
|
docker compose run --rm api politrack enrich
|
|
docker compose run --rm api politrack status
|
|
curl -s localhost:8000/api/v1/stats
|
|
```
|
|
|
|
`--max-requests` keeps test runs polite. Each run is recorded in the `run` table (stats, errors) and
|
|
shown by `politrack status` and `/api/v1/admin/runs`.
|
|
|
|
## Frontend
|
|
|
|
`npm run typecheck` (strict TypeScript against the generated API types) and `npm run build`.
|