Вступление
Привет, Хабр! Меня зовут Илья, я работаю Manual QA в команде, которая отвечает за качество продукта с большим количеством микросервисов, API и регулярными релизами. Если вы хоть раз писали тест-кейсы по тикету из Jira, потом руками собирали Postman-коллекцию по OpenAPI-спецификации, а после ревью документации обнаруживали, что половину сценариев забыли — эта статья для вас.
Я собрал инструмент, который автоматизирует три самых рутинных задачи QA-инженера: генерацию тест-кейсов, генерацию API-тестов и ревью документации. Всё это под одной крышей, с поддержкой любого OpenAI-совместимого LLM (включая локальные модели), с интеграциями в Jira, Confluence, TestRail, TestIT и Zephyr Scale.
Проект называется Test Generator Suite (TGS), и в этой статье я расскажу, какие проблемы он решает и как устроен внутри. Сразу оговорюсь: я не разработчик, я QA, и большую часть кода писал «как умею» — поэтому если в архитектурных решениях вам что-то покажется странным, я заранее согласен. Это инструмент для коллег по цеху, а не образец Python-инженерии.
Проблематика: почему я вообще за это взялся
QA-инженер в любой более-менее зрелой команде тратит огромное количество времени на повторяющиеся операции, которые с одной стороны требуют экспертизы, а с другой — большая их часть состоит из механического перекладывания информации из одной формы в другую.
Разберём типичный цикл моей работы над одной фичей. Аналитик пишет требования в Confluence, менеджер заводит задачу в Jira, разработчик прикладывает обновлённый OpenAPI-контракт. Я открываю эту задачу и начинаю делать примерно следующее: читаю описание, иду в Confluence по ссылке, смотрю спецификацию, формулирую у себя в голове сценарии, потом аккуратно раскладываю их по шаблону «название → предусловия → шаги → ожидаемый результат», заношу всё это в Zephyr Scale, после чего открываю Postman, дописываю к каждому эндпоинту проверки, тесты на негативные сценарии, валидацию схем ответа.
На крупной фиче этот процесс занимает день. И ведь это не творческая работа: 80% времени уходит на то, чтобы аккуратно зафиксировать то, что и так понятно из требований. Все решают эту проблему по разному: одни нанимают больше людей, другие выгорают, третьи ищут способы автоматизации. Я выбрал путь делегирования рутины LLM.
Параллельно с этим есть проблема качества входных данных. Если документация в задаче неполная или неоднозначная — тесты получатся такие же. Хороший тестировщик отлавливает это на этапе ревью документации, но это ещё один отдельный навык, который не у всех есть, и в любом случае это снова рутина: пройтись чек-листом по описанию и оценить, что забыли.
Из этих наблюдений и родилась идея TGS.
Что такое Test Generator Suite
Test Generator Suite — это веб-приложение на FastAPI, которое объединяет в себе три модуля, закрывающих основные сценарии моей работы.
Первый модуль — API-тесты. Я указываю Git-репозиторий с OpenAPI-спецификациями, выбираю нужные эндпоинты, и приложение клонирует репозиторий, разворачивает все внешние $ref-ссылки в единый документ, отправляет это в выбранную LLM-модель и возвращает готовую Postman-коллекцию v2.1 со всеми проверками: позитивные и негативные сценарии, валидация схем ответа, тесты на граничные значения. Коллекцию можно тут же отредактировать и запустить через встроенный Newman-runner, закоммитить обратно в репозиторий с коллекциями или скачать Postman коллекцию для глубокой доработки.
Второй модуль — Тест-кейсы. Я либо вписываю описание задачи руками, либо просто указываю номер Jira-тикета — приложение само подгружает описание из Jira и связанный контент из Confluence, отправляет это в LLM и возвращает структурированные тест-кейсы в едином формате. Их можно отредактировать прямо в UI и одной кнопкой залить в Zephyr Scale, TestRail или TestIT. Поддерживается работа с несколькими LLM одновременно — можно прогнать один и тот же ввод через GPT-4o и DeepSeek и сравнить результаты, есть feedback-петля: если в первой итерации что-то получилось не так, можно дать модели обратную связь и получить улучшенную версию.
Третий модуль — Doc Review. Это про качество входных данных. Модуль берёт описание задачи и прогоняет его через LLM с заточенным промптом, который оценивает полноту требований, тестируемость каждого пункта и потенциальные риски. На выходе — отчёт, который показывает, где в документации дыры, прежде чем по ней начнут писаться тесты. Это позволяет вернуть задачу аналитику до того, как я потрачу на неё несколько часов.
По части моделей TGS работает с любым OpenAI-совместимым эндпоинтом: можно использовать публичные API (OpenAI, DeepSeek, Anthropic через прокси), а можно поднять полностью локальную модель через vLLM или Ollama.
Как это работает изнутри
TGS — монолитное FastAPI-приложение со слоистой архитектурой. Я специально не пошёл в микросервисы: для инструмента, которым пользуется команда из 10-30 человек, это было бы избыточной сложностью, тем более для одного QA-разработчика без бэкенд-бэкграунда.

API-слой (tgs/api/) делает только три вещи: валидирует входные данные через Pydantic, вызывает функции из tgs/services/ и маппит исключения в HTTP-коды. Никакой бизнес-логики в роутерах нет
В сервисном слое лежит вся осмысленная работа. Например, openapi_bundler решает классическую проблему больших OpenAPI-проектов, где спецификация разбита на десятки файлов через $ref — модуль рекурсивно разворачивает внешние ссылки в один документ, оставляя внутренние ссылки (#/components/schemas/Foo) как есть, потому что их понимают и Postman, и Swagger-UI. Циклические ссылки я оставляю без инлайна — иначе ушёл бы в бесконечный цикл. Удалённые HTTP-ссылки игнорирую принципиально: загружать YAML с произвольных URL по запросу пользователя — это потенциальный SSRF.
postman_generator собирает payload для LLM из bundled OpenAPI, списка выбранных эндпоинтов и, опционально, существующей Postman-коллекции (чтобы модель сохранила стиль именования тестов и структуру переменных). Ответ модели парсится с учётом того, что LLM любят оборачивать JSON в markdown-блоки ```json ``` этот мусор аккуратно срезается, потом проверяется наличие обязательных полей info и item. Если LLM вернул что-то, что не похоже на коллекцию — кидаю понятную ошибку с первыми 500 символами ответа, чтобы можно было быстро понять, что пошло не так.
testcase_parser решает обратную задачу: LLM возвращает тест-кейсы в фиксированном Markdown-подобном формате, и парсер превращает этот текст в структуру, пригодную для UI и TMS. Я сделал его устойчивым к небольшим вариациям: модель может слегка нарушить регистр заголовков, перепутать число шагов с числом ожидаемых результатов — парсер это переживает без падения.
Слой tgs.llm — это OpenAI-совместимый клиент.
Добавление новой модели — это 6 строк в config.yaml:
models:
gpt4:
name: "GPT-4" # человекочитаемое имя в UI
api_key: ""
base_url: "https://api.openai.com/v1"
model_name: "gpt-4o"
temperature: 0.7
enabled: trueСлой tgs.tms — это адаптеры test-management-систем. Базовый интерфейс TestManagementClient и три реализации: Zephyr Scale, TestRail, TestIT (интеграция с TestRail и TestIT не тестировалась). Выбор активной системы — одно поле test_management_system: "zephyr" в конфиге. Чтобы добавить новую, нужно реализовать интерфейс и зарегистрировать в tms.factory.
tgs.integrations — это интеграции с Atlassian: Jira для загрузки тикетов и Confluence для подгрузки связанной документации. Когда я вписываю в UI номер тикета, приложение идёт в Jira, забирает описание, потом проходит по ссылкам на Confluence-страницы и собирает их содержимое — на выходе получается единый текстовый блок, который и уходит в LLM. Это сильно лучше, чем копипастить описание задачи руками — а первые пару месяцев я копипастил.
Конфигурация и безопасность
Все настройки читаются в трёх местах с понятным приоритетом: переменные окружения, потом config.yaml в рабочей директории, потом config.example.yaml как fallback. Это позволяет держать в git конфиг с URL серверов, но без секретов, а секреты передавать через .env или secret-менеджер кластера. В контейнере можно вообще не монтировать конфиг — всё передать через ENV.
Конфигурация типизирована через pydantic-settings. У всех полей есть типы, валидация происходит на старте. Если в config.yaml опечатка — приложение не стартует и сразу говорит, какое поле невалидно. Никаких runtime-сюрпризов в стиле «ой, тут забыли поле, давайте упадём через час работы».
Все секреты (API-ключи, пароли, токены) обёрнуты в pydantic.SecretStr. Это гарантирует, что они не попадут в логи через repr()/str() и не утекут в JSON-ответы FastAPI
По умолчанию приложение слушает только 127.0.0.1. Если нужен внешний доступ — ставите перед ним reverse-proxy (nginx, Caddy, Traefik) с TLS и аутентификацией.
Деплой
Три сценария на выбор. Самый простой — docker compose up -d: репозиторий, копирование примеров конфига, заполнение, поднятие. Compose монтирует config.yaml, директории logs/, output/ и repos_cache/ из хоста, образ остаётся неизменным между запусками.
Второй вариант — локальный pip install -e .. Подходит для разработки и для одиночного использования: после установки появляется CLI-команда tgs serve, которая поднимает uvicorn.
Третий вариант — production-деплой в кластер. Тут уже на ваш вкус: можно собрать образ и катить его через свой реестр, можно сделать systemd-юнит с uvicorn, можно завернуть в Helm-чарт. Healthcheck /healthz, логи в stderr (плюс файловая ротация 10 MB × 5 файлов), стейтлесс — масштабируется горизонтально без оговорок.
Что получилось в итоге
Хочу быть честным: TGS — это не серебряная пуля и не замена тестировщика. Это инструмент, который убирает рутину и оставляет человеку то, что он делает хорошо: проверять, дорабатывать, искать неочевидные сценарии. Я как Manual QA в первую очередь делал его под себя — чтобы перестать тратить день на то, что не приносит ценности.
Сгенерированные LLM тест-кейсы всегда требуют ревью. Postman-коллекции — тем более, особенно для сложных API с нетривиальными сценариями. Качество результата сильно зависит от модели: на gpt-4o или claude-3.5-sonnet всё получается достойно, на локальных моделях результат будет плох и окна контекста скорее всего не хватит. Это нормально, и в документации я это прямо указываю.
Зато то, на что у меня раньше уходил рабочий день, теперь занимает 15-20 минут вместе с ревью. И главное — я трачу это время на проверку и доработку, а не на механическое перекладывание текста между системами.
Заключение
Главный урок, который я вынес из этого проекта: LLM в QA-инструментах хорошо работает не тогда, когда заменяет тестировщика, а когда снимает с него самую рутинную часть работы. Сгенерировать первую версию тест-кейсов по описанию задачи — это рутина, которую модель делает за 30 секунд. Доработать, поймать пограничные сценарии, прогнать тесты, найти баг — это всё остаётся за человеком.
И второй урок, уже личный: даже если ты не разработчик, а Manual QA, ничто не мешает собрать инструмент под свою боль. Современные LLM закрывают огромную часть рутины разработки — мне они сильно помогли с тем, что я бы сам писал годами. А итоговая ценность для команды получилась сильно больше, чем затраты времени.
Технологический стек, если коротко:
Backend: Python 3.10+, FastAPI, pydantic, pydantic-settings, httpx, GitPython, PyYAML.
Frontend: чистый HTML/JS без фреймворков. Это инструмент, а не SPA — реакта тут не нужно.
LLM: любой OpenAI-совместимый провайдер.
TMS: Zephyr Scale, TestRail, TestIT через REST API.
Atlassian: Jira, Confluence через REST API.
Test runner: Newman (опционально, для прогона сгенерированных коллекций).
Деплой: Docker, docker-compose, systemd-юнит, любой ASGI-runner.
Линт/типы/тесты: ruff, mypy, pytest.
Лицензия — MIT. Ссылка на репозиторий
Буду рад вопросам и обратной связи в комментариях или в Телеграмм @ilyaakrickij.













