Модуль 12 · Урок 47 із 58
FastAPI architecture і contract testing
API test має доводити поведінку через HTTP boundary, а не лише викликати handler як звичайну function. Testable architecture відділяє transport, use case та persistence, щоб contract перевірявся швидко, детерміновано й без production side effects.
Безпечна FastAPI-практика модуля 12
Пакет містить synthetic SprintBoard API, Pydantic v2 models, dependencies, Problem Details, middleware, TestClient і OpenAPI contract tests. Він не відкриває зовнішню мережу під час tests, не містить authentication substitutes, персональних чи production-даних, credentials або production endpoints.
Transport, service і repository мають різні ролі
Router читає HTTP input і формує HTTP output. Service реалізує use-case policy. Repository ховає persistence details. Pydantic transport models не замінюють domain model, а SQL query не повинен жити всередині path operation.
APIRouter групує operations за resource. Application factory корисна, коли tests або environments потребують різного wiring, але не варто додавати factory лише заради абстракції без реальної потреби.
TestClient перетинає ASGI boundary
FastAPI TestClient походить зі Starlette й у поточному стеку використовує HTTPX2. Він викликає application in-process: не відкриває public port, але проходить routing, dependencies, validation, middleware, exception handlers та response serialization.
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_missing_task_is_problem_details():
response = client.get("/tasks/999")
assert response.status_code == 404
assert response.headers["content-type"].startswith(
"application/problem+json"
)
assert response.json()["type"].endswith("/task-not-found")Test не залежить від зовнішньої мережі, real customer data або production credentials.
Dependency override створює isolated scenario
Кожен test отримує fresh in-memory repository або disposable database. Override вмикають перед request і прибирають у finally чи fixture teardown. Так success, conflict і missing cases не залежать від order запуску.
Global mutable state маскує bugs
Якщо один test створив task, а інший випадково його використав, suite може пройти лише у певному order. Fresh fixture й explicit seed роблять evidence відтворюваним.
Contract suite перевіряє більше за status
Для кожної operation потрібні method/path, success status, response shape, headers, validation failures, domain failures і side-effect count. Для create workflow тестують 201, Location, output filtering та duplicate policy. Для list — limit boundaries, empty result і stable order.
| Layer evidence | Приклад assertion |
|---|---|
| HTTP | 201/404/409/422 і Content-Type |
| Schema | Required fields, types, no internal note |
| Behavior | Create додає рівно один resource |
| Docs | OpenAPI має stable operationId і responses |
| Isolation | Fresh repository у кожному test |
OpenAPI теж є test artifact
Test читає app.openapi() або /openapi.json і перевіряє critical operations, component schemas та response declarations. Повний snapshot часто шумний через framework updates, тому спочатку фіксують business-critical subset або semantic diff.
Practice pack модуля містить synthetic SprintBoard API, real in-process FastAPI requests, dependency override, validation/error handlers та OpenAPI checks. Він не містить authentication: identity, password hashing, tokens і authorization boundaries будуть реалізовані в модулі 13, після чого з’явиться review-проєкт 3.
- Зберіть application із явним wiring.
- Перевірте positive та negative HTTP contracts.
- Доведіть output filtering і відсутність secrets.
- Перевірте OpenAPI critical subset.
- Запускайте suite локально до кожної зміни contract.
Методичні джерела
Урок, сценарії, пояснення й вправи створені SEOWORK. Посилання ведуть на офіційну документацію framework та стандартів.
Закріпіть матеріал уроку
Три сценарні питання. Для зарахування уроку потрібно дати щонайменше дві правильні відповіді.