# Tests Automated test suite (pytest). Runs entirely against an **in-memory SQLite** database (`TestingConfig`) โ€” it never touches MySQL, sends mail, or hits the network, so it's safe to run anywhere. ## Running ```bash pip install -r requirements-dev.txt pytest ``` ## Layout | File | Covers | |---|---| | `test_score.py` | Inspection score calc โ€” correctness **and** web/API parity (the two hand-mirrored implementations must agree; CLAUDE.md ยง9 / rule 40). | | `test_sla.py` | SLA engine: `sla_status` / `sla_deadline` / `sla_hours_remaining` across every severity tier and boundary. | | `test_public_pages.py` | Login-free QR pages (`/f/`, `/f/area/`): rule 74 occupant-safety (no leaked checklist names / scores / descriptions), 404s, and the report-a-problem flow. | | `test_models.py` | `User.display_name`, `Issue.handler_label` / `resolved_facility`, public-token minting, and the authenticated area-QR route. | ## How the fixtures work (`conftest.py`) - Required env vars (`SECRET_KEY`, `DATABASE_URL`, `DIGEST_SECRET`) are set at import top **before** `app`/`config` import, because `config.py` reads them at import time. - The Flask app is built **once per session** โ€” `create_app()` can't run twice (the `api_bp` sub-blueprints are registered on a module-level singleton). - A **fresh app context + schema** is created per test. The per-test context matters: Flask-Login caches the current user on `g` (bound to the app context), so a shared context would leak an authenticated user between tests. - Factory fixtures (`make_user`, `make_facility`, `make_area`, `make_template`, `make_inspection`, `make_issue`) build persisted rows; pass only what you care about. `login(user)` authenticates via the real login route.