Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Практика: Контракты для Todo API
contract_testing_todo_api

Практика: Контракты для Todo API

Настраиваем контрактные тесты между Frontend и Backend Todo-приложения. Ловим breaking changes до продакшена

Применим contract testing к реальному Todo API: GET, POST, PUT, DELETE.

Цель: Создать полный набор контрактов для защиты API.

Контракты для Todo API

GET /api/todos - List todos

{ "endpoint": "GET /api/todos", "query_params": { "status": { "enum": ["all", "pending", "completed"] } }, "response": { "type": "array", "items": { "type": "object", "required": ["id", "title", "completed"], "properties": { "id": { "type": "integer" }, "title": { "type": "string", "maxLength": 255 }, "completed": { "type": "boolean" }, "created_at": { "type": "string", "format": "date-time" } } } } }

POST /api/todos - Create todo

{ "endpoint": "POST /api/todos", "request_body": { "type": "object", "required": ["title"], "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 255 } } }, "response": { "status_code": 201, "body": { "type": "object", "required": ["id", "title", "completed"], "properties": { "id": { "type": "integer" }, "title": { "type": "string" }, "completed": { "type": "boolean" } } } } }

Provider tests

# backend/tests/test_todo_contracts.py import pytest import jsonschema import json from pathlib import Path CONTRACTS_DIR = Path(__file__).parent.parent / "contracts" def load_contract(name): """Load contract schema""" with open(CONTRACTS_DIR / f"{name}.json") as f: return json.load(f) def test_get_todos_contract(client): """GET /api/todos matches contract""" contract = load_contract("get_todos") response = client.get("/api/todos") assert response.status_code == 200 jsonschema.validate(response.json(), contract["response"]) def test_create_todo_contract(client): """POST /api/todos matches contract""" contract = load_contract("create_todo") response = client.post("/api/todos", json={"title": "Test Todo"}) assert response.status_code == contract["response"]["status_code"] jsonschema.validate(response.json(), contract["response"]["body"]) def test_create_todo_invalid_request(client): """Invalid request body""" contract = load_contract("create_todo") # Missing required field response = client.post("/api/todos", json={}) assert response.status_code == 422 # Validation error

Проверьте свои знания

Вопросы ещё не добавлены

Вопросы для этой подтемы ещё не добавлены.

Далее: CI/CD: Параллельный запуск и шардирование