Модуль 12 · Урок 47 із 58

FastAPI architecture і contract testing

API test має доводити поведінку через HTTP boundary, а не лише викликати handler як звичайну function. Testable architecture відділяє transport, use case та persistence, щоб contract перевірявся швидко, детерміновано й без production side effects.

ArchitectureTestClientOverridesContracts

Безпечна 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.

RouterMethods, paths, validation, statuses.
ServiceBusiness invariants та orchestration.
RepositoryPersistence contract і transactions.
ApplicationWiring, middleware, handlers, routers.

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
HTTP201/404/409/422 і Content-Type
SchemaRequired fields, types, no internal note
BehaviorCreate додає рівно один resource
DocsOpenAPI має stable operationId і responses
IsolationFresh 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.

  1. Зберіть application із явним wiring.
  2. Перевірте positive та negative HTTP contracts.
  3. Доведіть output filtering і відсутність secrets.
  4. Перевірте OpenAPI critical subset.
  5. Запускайте suite локально до кожної зміни contract.

Методичні джерела

Урок, сценарії, пояснення й вправи створені SEOWORK. Посилання ведуть на офіційну документацію framework та стандартів.

Практична перевірка · урок 47 з 47

Закріпіть матеріал уроку

Три сценарні питання. Для зарахування уроку потрібно дати щонайменше дві правильні відповіді.

1. Path operation одночасно parse HTTP, виконує SQL, рахує domain policy й формує email. Яке розділення найбільш testable?
2. Що саме проходить FastAPI TestClient на відміну від прямого виклику handler function?
3. Два tests використовують один mutable in-memory repository й залежать від order. Як виправити suite?