47 lines
1.4 KiB
Markdown
47 lines
1.4 KiB
Markdown
|
|
# Backend Tests
|
||
|
|
|
||
|
|
## Framework
|
||
|
|
|
||
|
|
pytest + FastAPI `TestClient` (sync, in-process). No database mocking needed — tests hit real endpoints with real data files.
|
||
|
|
|
||
|
|
## Structure
|
||
|
|
|
||
|
|
- `conftest.py` — shared fixtures (`client`, `auth_headers`, test data)
|
||
|
|
- `test_api.py` — endpoint integration tests, organized by router class
|
||
|
|
- `test_auth.py` — authentication flow tests
|
||
|
|
- `test_error_handling.py` — edge cases, error responses
|
||
|
|
- `test_utils.py` — pure utility function tests
|
||
|
|
|
||
|
|
## Patterns
|
||
|
|
|
||
|
|
- Tests organized in classes: `class TestRiskEndpoints:`
|
||
|
|
- One test method per scenario: `test_current_risk_map()`, `test_risk_map_with_date()`
|
||
|
|
- Fixture naming: `client: TestClient`, `auth_headers: dict`
|
||
|
|
- Assert response status, then JSON structure, then field types/values
|
||
|
|
|
||
|
|
```python
|
||
|
|
class TestSomeRouter:
|
||
|
|
def test_something(self, client: TestClient):
|
||
|
|
resp = client.get("/api/some/endpoint")
|
||
|
|
assert resp.status_code == 200
|
||
|
|
data = resp.json()
|
||
|
|
assert "key" in data
|
||
|
|
assert isinstance(data["key"], list)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Running
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cd backend
|
||
|
|
source venv/bin/activate
|
||
|
|
pytest tests/ -v
|
||
|
|
pytest tests/test_api.py -v -k "test_risk"
|
||
|
|
```
|
||
|
|
|
||
|
|
## Anti-Patterns
|
||
|
|
|
||
|
|
- Don't mock endpoints you can test with real data
|
||
|
|
- Don't hardcode test dates that will go stale
|
||
|
|
- Don't skip assertions on response structure just because status is 200
|
||
|
|
- Don't share mutable state between test classes — use fixtures
|