Flash out API test suite
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
# Backend API Test Guide
|
||||
|
||||
This directory contains the backend API test suite. The tests use pytest, FastAPI's `TestClient`, and an isolated in-memory SQLite database. The goal is to cover the business-critical API behaviour without relying on MySQL, Redis, SMTP, or a running browser.
|
||||
|
||||
## How To Run
|
||||
|
||||
From `backend/`:
|
||||
|
||||
```bash
|
||||
pytest
|
||||
pytest --cov=app --cov-report=term-missing
|
||||
```
|
||||
|
||||
From the project root with Docker Compose running:
|
||||
|
||||
```bash
|
||||
docker compose exec api pytest
|
||||
docker compose exec api pytest --cov=app --cov-report=term-missing
|
||||
```
|
||||
|
||||
## Shared Fixtures
|
||||
|
||||
### `conftest.py`
|
||||
|
||||
Sets up the test harness used by every module.
|
||||
|
||||
What it does:
|
||||
- Provides safe default environment variables before the app imports settings.
|
||||
- Creates an in-memory SQLite database and overrides FastAPI's `get_db` dependency.
|
||||
- Recreates all tables for every test so tests cannot leak state into each other.
|
||||
- Patches SQLite primary-key handling for models that use `BigInteger` ids in production.
|
||||
- Provides `client` for unauthenticated requests and `auth_client` for administrator/operator requests.
|
||||
- Provides reusable PPR payload and factory fixtures.
|
||||
|
||||
Why it exists:
|
||||
- Keeps API tests fast, deterministic, and independent from Docker MySQL data.
|
||||
- Lets tests exercise the real FastAPI routes, schemas, CRUD calls, and dependency overrides.
|
||||
|
||||
## Test Modules
|
||||
|
||||
### `test_app_health.py`
|
||||
|
||||
Covers the simplest application-level endpoints.
|
||||
|
||||
What it tests:
|
||||
- `/` returns API metadata.
|
||||
- `/health` reports a healthy application and database connection.
|
||||
|
||||
Why it matters:
|
||||
- These tests catch broken app imports, router setup problems, and database dependency regressions early.
|
||||
|
||||
### `test_auth_api.py`
|
||||
|
||||
Covers authentication and admin user-management routes.
|
||||
|
||||
What it tests:
|
||||
- Login rejects invalid credentials.
|
||||
- Login returns a bearer token for a valid user.
|
||||
- Admin users can create, list, update, and change passwords for users.
|
||||
- Duplicate users and missing users return the expected errors.
|
||||
|
||||
Why it matters:
|
||||
- Auth is the gatekeeper for most operational endpoints.
|
||||
- The admin user flow is also a good end-to-end check of password hashing, token creation, CRUD, and journal side effects.
|
||||
|
||||
### `test_pprs_api.py`
|
||||
|
||||
Covers the core PPR lifecycle.
|
||||
|
||||
What it tests:
|
||||
- PPR routes require authentication where appropriate.
|
||||
- Authenticated users can create, read, update, patch, acknowledge, status-update, soft-delete, and audit PPRs.
|
||||
- List filters work for status, dates, skip, and limit.
|
||||
- Public PPR creation sends email and generates secure edit tokens.
|
||||
- Public edit and cancel token flows work and reject invalid or processed requests.
|
||||
- Activation creates an arrival and pending departure.
|
||||
- Missing PPRs return 404.
|
||||
- Invalid payloads return validation errors.
|
||||
|
||||
Why it matters:
|
||||
- PPRs are the central workflow in the system.
|
||||
- These tests protect the operational state transitions that drive tower/admin views and audit history.
|
||||
|
||||
### `test_public_api.py`
|
||||
|
||||
Covers public read-only board and lookup endpoints.
|
||||
|
||||
What it tests:
|
||||
- Public arrivals and departures start empty.
|
||||
- Today's PPRs, local flights, arrivals, and departures appear on public boards.
|
||||
- Old or cancelled records are excluded.
|
||||
- Public airport and aircraft lookups return seeded records.
|
||||
- Short or invalid lookup queries return empty lists.
|
||||
|
||||
Why it matters:
|
||||
- Public boards and lookup helpers are user-facing and unauthenticated.
|
||||
- These tests check that the public API exposes useful operational information without requiring login.
|
||||
|
||||
### `test_flight_strip_apis.py`
|
||||
|
||||
Covers authenticated flight-strip style CRUD endpoints.
|
||||
|
||||
What it tests:
|
||||
- Arrival lifecycle: create, list/filter, read, update, land, cancel, and not-found paths.
|
||||
- Landing an arrival promotes a linked pending departure.
|
||||
- Departure lifecycle: create, list/filter, update, takeoff/departure status, cancel, and not-found paths.
|
||||
- Local flight lifecycle: create, list/filter, update, depart, land, special lists, cancel, and not-found paths.
|
||||
- Overflight lifecycle: create, active/today lists, list/filter, update, mark inactive/QSY, cancel, and not-found paths.
|
||||
- Movement records are created for real takeoff, landing, touch-and-go, and overflight events where relevant.
|
||||
|
||||
Why it matters:
|
||||
- These endpoints represent day-to-day tower strip operations.
|
||||
- They also exercise important CRUD side effects: status timestamps, movements, linked departures, and journal entries.
|
||||
|
||||
### `test_circuits_api.py`
|
||||
|
||||
Covers circuit/touch-and-go records.
|
||||
|
||||
What it tests:
|
||||
- Circuits can be recorded for local flights.
|
||||
- Circuits can be recorded for arrivals.
|
||||
- Circuit list, lookup-by-flight, lookup-by-arrival, update, and delete work.
|
||||
- Invalid circuit creation requests are rejected when neither or both parent ids are supplied.
|
||||
- Missing circuits return 404.
|
||||
- Recording a circuit creates a touch-and-go movement.
|
||||
|
||||
Why it matters:
|
||||
- Circuit traffic is a distinct operational pattern and feeds movement logging.
|
||||
- The parent-id validation prevents ambiguous audit/movement records.
|
||||
|
||||
### `test_movements_api.py`
|
||||
|
||||
Covers movement listing, context lookup, and bulk paper-strip logging.
|
||||
|
||||
What it tests:
|
||||
- Movement list filters and single-record reads.
|
||||
- Bulk movement context suggests matching PPRs and existing movements.
|
||||
- Bulk logging can create and update PPR-linked arrivals.
|
||||
- Bulk logging can create unmatched arrival and departure records.
|
||||
- Bulk logging handles local flight strips with takeoff, landing, duration, and circuits.
|
||||
- Bulk logging handles overflight strips and updates existing overflight records.
|
||||
- Invalid bulk-log requests return helpful 400 errors.
|
||||
|
||||
Why it matters:
|
||||
- Bulk movement logging is one of the densest workflows in the API.
|
||||
- These tests protect the behaviour that translates paper-strip data into PPR, arrival, departure, local flight, overflight, movement, and journal records.
|
||||
|
||||
### `test_drone_requests_api.py`
|
||||
|
||||
Covers drone flight request workflows.
|
||||
|
||||
What it tests:
|
||||
- Public drone request creation generates references/tokens and sends confirmation email.
|
||||
- Public edit and cancel token flows work.
|
||||
- Processed drone requests cannot be edited or cancelled publicly.
|
||||
- Authenticated users can list, read, update, status-update, comment on, and audit drone requests.
|
||||
- Missing records and invalid payloads return expected errors.
|
||||
|
||||
Why it matters:
|
||||
- Drone requests are a newer workflow with public and authenticated surfaces.
|
||||
- The tests protect email notification, public token, status, comment, and journal behaviour.
|
||||
|
||||
### `test_public_book_api.py`
|
||||
|
||||
Covers the optional public booking portal.
|
||||
|
||||
What it tests:
|
||||
- Public booking rejects requests when disabled.
|
||||
- Public local flight booking creates a public-submitted local flight.
|
||||
- Public circuit recording creates a circuit and touch-and-go movement.
|
||||
- Public departure and arrival booking create public-submitted records with pilot emails.
|
||||
- Invalid public booking payloads return validation errors.
|
||||
|
||||
Why it matters:
|
||||
- Public booking is controlled by configuration and should be safe to disable.
|
||||
- When enabled, it creates operational records without authentication, so validation and submitted-via metadata matter.
|
||||
|
||||
### `test_journal_api.py`
|
||||
|
||||
Covers generic audit/journal endpoints.
|
||||
|
||||
What it tests:
|
||||
- Journal search filters by date, entity type, entity id, and user.
|
||||
- Invalid entity types are rejected.
|
||||
- User journal and entity journal endpoints return entries and summary counts.
|
||||
|
||||
Why it matters:
|
||||
- The journal is the audit trail across PPRs, flights, users, drone requests, and movements.
|
||||
- These tests make sure audit entries remain queryable as the system grows.
|
||||
|
||||
## Current Scope
|
||||
|
||||
The suite intentionally focuses on API behaviour and database side effects. It does not deeply test:
|
||||
- WebSocket connection lifecycle and Redis pub/sub behaviour.
|
||||
- Real SMTP delivery.
|
||||
- Browser UI behaviour.
|
||||
- Every branch of low-level validators or helper functions.
|
||||
|
||||
Those areas are better handled with focused unit tests or E2E tests later.
|
||||
Reference in New Issue
Block a user