Modern QA2026Живая документация API
Join

Course04 API & Contract Testing with AI

Cutting-edge · Chapter 04

Живая документация API

Updated Jul 2026

Проблема устаревания документации

API-документация устаревает за считанные недели после написания. Инженеры меняют конечные точки, добавляют поля, корректируют коды ошибок -- но забывают обновить документацию. Это создаёт опасный разрыв: потребители разрабатывают против документации, а реализация уже расходится.

ИИ-агенты могут решить эту проблему, непрерывно сравнивая реализацию с документацией и создавая pull request'ы для исправления расхождений.

Архитектура агента для живой документации

class APIDocumentationAgent:
    """Agent that keeps API documentation synchronized with implementation."""

    def __init__(self, llm, repo_path: str, spec_path: str):
        self.llm = llm
        self.repo_path = repo_path
        self.spec_path = spec_path

    def daily_sync(self):
        """Run daily to detect and fix documentation drift."""

        # Step 1: Extract actual API behavior from code
        routes = self.extract_routes_from_code()

        # Step 2: Parse current documentation
        documented = self.parse_openapi_spec()

        # Step 3: Compare and find drifts
        drifts = self.compare(routes, documented)

        # Step 4: For each drift, generate a fix
        fixes = []
        for drift in drifts:
            if drift.type == "UNDOCUMENTED_ENDPOINT":
                fix = self.generate_endpoint_docs(drift.endpoint)
                fixes.append(fix)
            elif drift.type == "MISSING_FIELD":
                fix = self.generate_field_docs(drift.endpoint, drift.field)
                fixes.append(fix)
            elif drift.type == "STALE_EXAMPLE":
                fix = self.regenerate_example(drift.endpoint)
                fixes.append(fix)

        # Step 5: Create a PR with the fixes
        if fixes:
            self.create_documentation_pr(fixes)

    def extract_routes_from_code(self) -> list:
        """Use AI to parse route definitions from the source code."""
        prompt = f"""
        Analyze the following source files and extract all API routes.
        For each route, identify:
        - HTTP method and path
        - Request body schema (from validation decorators or type hints)
        - Response schema (from return statements or serializer usage)
        - Authentication requirements
        - Status codes returned

        Source files:
        {self.read_route_files()}
        """
        return self.llm.generate_structured(prompt, schema=RouteList)

    def compare(self, actual_routes, documented_routes) -> list:
        """Compare actual routes against documentation."""
        drifts = []

        actual_paths = {(r.method, r.path) for r in actual_routes}
        documented_paths = {(r.method, r.path) for r in documented_routes}

        # Undocumented endpoints
        for method, path in actual_paths - documented_paths:
            drifts.append(Drift(
                type="UNDOCUMENTED_ENDPOINT",
                endpoint=f"{method} {path}",
                message=f"Endpoint exists in code but not in documentation"
            ))

        # Documented but removed endpoints
        for method, path in documented_paths - actual_paths:
            drifts.append(Drift(
                type="REMOVED_ENDPOINT",
                endpoint=f"{method} {path}",
                message=f"Endpoint in documentation but not found in code"
            ))

        # Field-level comparison for shared endpoints
        for method, path in actual_paths & documented_paths:
            actual = next(r for r in actual_routes if r.method == method and r.path == path)
            documented = next(r for r in documented_routes if r.method == method and r.path == path)
            drifts.extend(self.compare_fields(actual, documented))

        return drifts

    def create_documentation_pr(self, fixes: list):
        """Create a git branch, apply fixes, and open a PR."""
        branch_name = f"docs/api-sync-{datetime.now().strftime('%Y%m%d')}"

        # Create branch
        subprocess.run(["git", "checkout", "-b", branch_name], cwd=self.repo_path)

        # Apply each fix to the OpenAPI spec
        spec = yaml.safe_load(open(self.spec_path))
        for fix in fixes:
            self.apply_fix(spec, fix)
        yaml.dump(spec, open(self.spec_path, "w"), default_flow_style=False)

        # Commit and push
        subprocess.run(["git", "add", self.spec_path], cwd=self.repo_path)
        subprocess.run(
            ["git", "commit", "-m", f"docs: sync API documentation ({len(fixes)} fixes)"],
            cwd=self.repo_path
        )
        subprocess.run(["git", "push", "origin", branch_name], cwd=self.repo_path)

        # Create PR via GitHub CLI
        pr_body = self.generate_pr_body(fixes)
        subprocess.run([
            "gh", "pr", "create",
            "--title", f"docs: sync API documentation ({len(fixes)} fixes)",
            "--body", pr_body,
            "--base", "main",
        ], cwd=self.repo_path)

Многоуровневая стратегия тестирования API

Собирая всё воедино, стратегия тестирования API на базе ИИ имеет шесть уровней:

Layer 1: CONTRACT TESTS (Pact)
  -- Consumer expectations published to broker
  -- Provider verification runs on every PR
  -- AI generates and updates contracts from client code

Layer 2: SCHEMA VALIDATION (OpenAPI)
  -- AI generates test suite from schema
  -- Drift detection runs daily
  -- Response shape validation on every endpoint

Layer 3: FUNCTIONAL TESTS (pytest + httpx)
  -- AI generates from schema + business rules
  -- Human curates for domain correctness
  -- Runs on every PR

Layer 4: SEMANTIC FUZZING
  -- AI generates contextually meaningful payloads
  -- Runs nightly on staging
  -- Anomalies triaged by AI, confirmed by human

Layer 5: EVENT-DRIVEN TESTS (Kafka/SQS/EventBridge)
  -- Event publication and consumption verification
  -- Idempotency and ordering tests
  -- Dead letter queue monitoring

Layer 6: LIVING DOCUMENTATION
  -- AI agent compares code to docs daily
  -- Generates PRs for drift fixes
  -- Human reviews and merges

Анализ затрат и выгод по уровням

Уровень Стоимость настройки Стоимость поддержки Ценность обнаружения багов Использование ИИ
Контрактные тесты Средняя Низкая (автообновление) Высокая (интеграция) Высокое
Валидация схемы Низкая Очень низкая Средняя (структура) Очень высокое
Функциональные тесты Средняя Средняя Высокая (логика) Высокое
Семантический фаззинг Низкая Очень низкая Высокая (безопасность) Очень высокое
Событийные тесты Высокая Средняя Высокая (асинхронность) Среднее
Живая документация Низкая Очень низкая Средняя (точность) Очень высокое

Запуск полной стратегии в CI

# .github/workflows/api-testing.yml
name: API Test Strategy

on:
  pull_request:
    paths: ['app/**', 'docs/openapi.yaml']

jobs:
  contract-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run pact:test
      - run: npm run pact:publish

  schema-validation:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: python -m pytest tests/api/ -v

  functional-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: docker-compose up -d
      - run: python -m pytest tests/functional/ -v --cov=app

  # Nightly only
  semantic-fuzzing:
    if: github.event.schedule
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: docker-compose up -d
      - run: python -m api_fuzzer --output fuzz-report.json

  # Nightly only
  drift-detection:
    if: github.event.schedule
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: docker-compose up -d
      - run: python -m schema_drift_detector --output drift-report.json

Тезис для собеседования

«Я рассматриваю API-тестирование в нескольких уровнях, и ИИ играет разную роль на каждом. На уровне контрактов ИИ анализирует наш клиентский код и автоматически генерирует потребительские тесты Pact -- он обнаруживает каждый паттерн HTTP-вызова и строит ожидания контракта. На уровне схемы ИИ генерирует комплексные тесты из нашей OpenAPI-спецификации, покрывая каждое ограничение полей, значение enum и сценарий авторизации. На уровне фаззинга ИИ генерирует семантически осмысленные данные -- не случайные байты, а строки SQL-инъекций в полях имён, граничные значения для цен, краевые случаи Unicode -- что находит реальные уязвимости, которые случайный фаззинг пропускает. Для событийно-ориентированных архитектур я сосредотачиваюсь на идемпотентности, порядке и тестировании dead-letter, потому что именно в этих местах асинхронные системы незаметно ломаются. Самая недооценённая возможность -- обнаружение дрейфа схемы: ИИ-агент ежедневно сравнивает нашу OpenAPI-спецификацию с реальным поведением API и создаёт PR всякий раз, когда документация устаревает. Это устраняет целый класс багов "документация говорит X, а API делает Y", который преследует каждую микросервисную команду, с которой я работал.»

Ключевой вывод

Живая документация -- последний уровень API-тестирования на базе ИИ. ИИ-агент, который запускается ежедневно, сравнивает вашу OpenAPI-спецификацию с реальным поведением API и создаёт PR при расхождениях, устраняет целый класс багов устаревания документации. В сочетании с другими пятью уровнями (контракты, валидация схемы, функциональные тесты, фаззинг, событийные тесты) это создаёт комплексную систему качества API, где ИИ выполняет систематическую работу, а люди сосредоточены на доменных решениях и ревью.