Гайд: API автотесты из Swagger через OpenAPI Generator, Cursor, Claude Code | AiManual
AiManual Logo Ai / Manual.
24 Июн 2026 Гайд

Генерация API-автотестов из Swagger с помощью OpenAPI Generator, Cursor и Claude Code: полное руководство

Пошаговое руководство по генерации API-автотестов из Swagger/OpenAPI с помощью OpenAPI Generator, Cursor и Claude Code. Примеры кода, mustache-шаблоны, swagger-

Реклама
partv2

Почему ручное написание тестов — путь в никуда

Ты QA-инженер. У тебя есть Swagger-спецификация API на 200+ эндпоинтов. Тимлид говорит: «Покрытие тестами — 80% через месяц». Ты смотришь на эту спецификацию и понимаешь: писать тесты руками — это смерть. Не физическая, но карьерная. Потому что через две недели тебя ждет выгорание и очередной «срочный рефакторинг» API, который сломает половину написанных тестов.

В 2026 году так уже не работает. OpenAPI Generator давно умеет генерировать не только клиенты, но и каркасы тестов. Cursor с Claude Code превращает этот каркас в настоящие, живые тесты с реальными данными и валидацией. А swagger-coverage показывает, какие эндпоинты остались без проверок. В этом руководстве я разложу всю цепочку: от спецификации до CI-пайплайна, который сам себя проверяет.

Важный момент: мы не пишем тесты «с нуля». Мы генерируем 80% кода, а оставшиеся 20% — это логика аутентификации, генерация реалистичных payload’ов и проверка бизнес-правил. И эти 20% добивает AI.

Что нам понадобится (инструментарий 2026 года)

Прежде чем нырять в код, давай определимся с версиями. На июнь 2026 года актуальны:

  • OpenAPI Generator 7.12 — стабильная версия с поддержкой OpenAPI 3.1 и новыми шаблонами для тестов (JUnit 5, Pytest, Jest).
  • Cursor 0.45+ — с нативной интеграцией Claude Code 3 (без дополнительных прокси).
  • Claude Code (встроен в Cursor) — модель 3.5 Sonnet или Opus, которая отлично понимает OpenAPI-спецификации.
  • swagger-coverage 1.5 — инструмент, который парсит результаты тестов и рисует heatmap покрытия.
  • Node.js 22 или Java 21 (для генератора, если используешь JAR).
💡
Не советую использовать старые версии OpenAPI Generator (до 7.x) — они не поддерживают oneOf/anyOf в схемах, что приводит к дырявым тестам.

Шаг 1. Генерация тестового каркаса через OpenAPI Generator

1Установка и первый запуск

Проще всего использовать npm-пакет @openapitools/openapi-generator-cli. Он тянет за собой сам генератор.

npm install -g @openapitools/openapi-generator-cli
openapi-generator-cli version
# ожидаем: 7.12.0

Теперь генерируем тесты. Допустим, у нас есть petstore.yaml. Нам нужен генератор python-pytest (если пишешь на Python) или java-junit5. Я покажу на Python, потому что он ближе QA-инженерам.

openapi-generator-cli generate -i petstore.yaml \
    -g python-pytest \
    -o ./generated-tests \
    --additional-properties=library=urllib3,testPackage=test

На выходе получаем папку generated-tests/test/ с файлами вида test_pet_api.py. Внутри — методы с заглушками:

def test_add_pet(self):
    """Test case for add_pet"""
    body = {}  # TODO
    response = self.api.add_pet(body)
    # TODO: assert response

Заметил? Там пустой словарь, нет реальных данных, нет проверок статус-кода. И это нормально. OpenAPI Generator делает ровно то, что заложено в шаблонах — структуру. А наполнять будем дальше.

2Кастомные Mustache-шаблоны — почему они тебе нужны

Генератор использует Mustache-шаблоны. Если тебя не устраивает стандартный скелет (например, нет проверки response.status_code или не генерируется pytest.mark.parametrize), ты можешь переопределить шаблоны. Создай папку my-templates/python-pytest, скопируй туда дефолтные из репозитория генератора и меняй.

Вот фрагмент шаблона, который я докрутил, чтобы сразу вставлять примеры данных из examples спецификации:

def test_{{operationId}}(self):
    """Test case for {{operationId}}"""
    {{#bodyParam}}
    body = {{{vendorExtensions.x-example}}} if {{{vendorExtensions.x-example}}} else {}
    {{/bodyParam}}
    response = self.api.{{operationId}}({{#bodyParam}}body{{/bodyParam}})
    assert response.status_code == {{#defaultResponse}}{{statusCode}}{{/defaultResponse}}{{^defaultResponse}}200{{/defaultResponse}}

Затем генерируем с указанием кастомных шаблонов:

openapi-generator-cli generate -i petstore.yaml \
    -g python-pytest \
    -o ./generated-tests \
    -t ./my-templates/python-pytest

Важно: спецификация должна содержать поля example или examples, иначе шаблон не подхватит данные. Если спецификация от разработчиков без примеров — беда. Но об этом позже.

Шаг 2. Подключаем Cursor и Claude Code — превращаем болванку в настоящий тест

Сгенерированный код — это еще не тесты. Это скелет. Чтобы оживить его, нужен AI, который понимает контекст API. Открываем Cursor, делаем Ctrl+K (или Cmd+K) и вводим промпт:

У нас есть OpenAPI спецификация в файле petstore.yaml. 
В папке generated-tests/test/ лежат сгенерированные тесты. 
Для каждого теста:
1. Прочитай спецификацию и определи обязательные поля.
2. Сгенерируй реалистичные данные (используй faker или случайные UUID).
3. Добавь проверки статус-кода (200, 201, 404).
4. Если в ответе есть schema, добавь валидацию с помощью pydantic.
5. Учти, что некоторые эндпоинты требуют авторизации — для них передай токен из фикстуры.

Claude Code (через Cursor) анализирует и спецификацию, и код, и за несколько секунд дополняет файлы. Это не магия — это tool_use: модель читает файлы, пишет правки, запускает тесты и исправляет ошибки.

Я настоятельно советую прочитать статью Schema-enforced execution с tool_use: как повысить надежность структурированных ответов Claude до 95% — она как раз про то, как заставить модель не выдумывать, а строго следовать схеме ответа. В нашем контексте это критично: если Claude неправильно поймет тип поля, тест упадет.

Но есть нюанс: Claude может нагаллюцинировать фикстуры или пропустить статус-код. Чтобы этого избежать, используй локальный 'слой истины' для Claude Code. Этот «слой» — файл CLAUDE.md в корне проекта, в котором ты описываешь правила генерации тестов: какие библиотеки использовать, как называть тестовые данные, обязательные assert’ы.

Ошибка новичка: просто скормить AI весь код и надеяться, что он сделает идеально. Не делай так. Сначала настрой CLAUDE.md и проверь, что модель читает OpenAPI-спецификацию.

Шаг 3. Валидация ответов с помощью swagger-coverage

После того, как тесты написаны, нужно понять, что мы действительно покрыли все эндпоинты и все статус-коды. swagger-coverage (версия 1.5) собирает статистику на основе выполненных HTTP-запросов. Установка:

pip install swagger-coverage
swagger-coverage generate --spec petstore.yaml --results ./test-results

Запускаем тесты с записью трафика (например, через pytest --coverage), и получаем HTML-отчет. Красные эндпоинты — те, что не тестируются. Можно даже настроить порог: если покрытие ниже 70% — CI падает.

Кстати, вот отличный пример интеграции AI-агентов с тестированием: Эксперимент с автономным AI-разработчиком. Там показано, как настроить цикл «генерация тестов — прогон — исправление багов». В нашем случае swagger-coverage дает сигнал, какие сценарии не покрыты, и Claude Code может сгенерировать недостающие тесты.

Шаг 4. CI/CD: всё в одном пайплайне

Финальный аккорд — собрать всю цепочку в GitHub Actions (2026 год, но ничего не изменилось). Вот пример workflow:

name: API Tests Generation & Execution
on: [push]
jobs:
  generate-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
      - run: npm install -g @openapitools/openapi-generator-cli
      - run: openapi-generator-cli generate -i spec.yaml -g python-pytest -o ./tests -t ./templates
      - run: pip install -r tests/requirements.txt
      - run: pytest tests/ --coverage --coverage-output=coverage.json
      - run: swagger-coverage generate --spec spec.yaml --results coverage.json
      - uses: actions/upload-artifact@v4
        with:
          name: coverage-report
          path: coverage.html

Я умышленно не включаю сюда Cursor — он нужен разработчику, а не CI. В CI мы используем уже сгенерированные и доработанные AI тесты. Но если хочешь автоматизировать доработку и в CI, используй Claude Code: полное руководство — там описана настройка Claude Code в режиме CLI для CI.

Нюансы и грабли (собери их до того, как они соберут тебя)

  1. Спецификация без примеров — самая частая боль. Договаривайся с разработчиками, чтобы они добавляли example в схемы. Иначе AI-генерация данных будет случайной, а тесты — хрупкими.
  2. Аутентификация — OpenAPI Generator не умеет шарить токены между тестами. Придется дописать фикстуру вручную или докинуть промпт для Claude.
  3. Ретейсты — если тест упал, не давай CI сразу фейлиться. Добавь @pytest.mark.flaky(reruns=2), потому что некоторые API отвечают 500 при первом запросе.
  4. Совместимость версий — OpenAPI Generator 7.12 требует Java 11+, но лучше использовать Java 21, чтобы избежать deprecated warning.
  5. Mustache-шаблоны — если меняешь шаблон, перегенерируй все тесты заново. Частичное изменение может привести к непредсказуемым результатам.
«Мы потратили неделю на написание Mustache-шаблонов, зато потом экономили по 3 дня на каждом релизе». — цитата real QA Engineer, 2026

Неочевидный совет (читай, если хочешь быть лучшим)

Большинство гайдов заканчивается победной нотой «всё работает». Но реальность сложнее. Главная проблема сгенерированных тестов — они проверяют, что API отвечает, но не проверяют смысл ответа. Например, эндпоинт POST /users возвращает 201 с пользователем, но без поля email. Статус-код пройдет, а бизнес-логика — нет.

Решение: используй schema-enforced execution для генерации assert’ов на основе JSON Schema. Claude Code может по схеме ответа создать pydantic-модель и валидировать ответ строго. Это описано в статье Schema-enforced execution с tool_use. Примени тот же подход к тестам: пусть Claude генерирует assert’ы, которые проверяют не только код, но и структуру ответа.

И последнее: не пытайся автоматизировать всё. OpenAPI Generator + Cursor + Claude Code — это мощная цепочка, но она требует человеческого глаза. Ты — DevOps, ты знаешь, где тонко. Оставь себе 10% ручных проверок на самые критичные сценарии. А всё остальное пусть генерируется.

Подписаться на канал