Привет, Хабр!
Я Анна Круглова, в Диасофт занимаюсь развитием инструментов автоматизации тестирования на базе искусственного интеллекта.
В нашей компании процесс создания тестов для API и событий полностью автоматизирован с помощью ИИ. В этой статье расскажу, как это устроено и влияет на подход к работе тестировщика.
Особенности сложных API и событий
Для создания микросервисов и проектирования межсервисных взаимодействий (контракты API и событий) в Диасофт используется low-code платформа Digital Q.Archer, на базе которой генерируется код сервисов.
Ранее было автоматизировано создание автотестов только на стандартные CRUD API и события. Такие операции типовые и легко поддаются шаблонизации. Руками же приходилось создавать автотесты для API и событий, содержащих уникальную бизнес-логику.
Основная проблема заключалась в том, что стандартные CRUD-операции покрывали лишь малую часть функциональности реального продукта. Самая ценная и сложная часть – это как раз уникальные бизнес-процессы (расчет процентов, применение комиссий, обработка лимитов и т.д.). Ручное написание тестов для сотни таких сценариев требовало огромных трудозатрат и сдерживало скорость выхода релизов.
Сложные API и события не просто управляют данными, а реализуют конкретные бизнес-операции. Их «сложность» заключается в нетривиальной логике внутри: они могут менять состояние множества объектов, запускать цепочки связанных событий, требовать специфической последовательности вызовов и проверки особых условий. Просто проверить, что API вернул код 200, недостаточно. Нужно проверять, как именно изменились данные в системе, соответствуют ли эти изменения заложенной бизнес-логике.
ИИ пишет тест как опытный разработчик: как так получилось?
Мы не просто точечно взяли ИИ и «прибили гвоздями» к процессу выпуска продукта. Мы встроили его в существующий технологический конвейер платформы Digital Q.DevOps. Это не отдельный инструмент, а полноценный Агент автотестирования, являющийся частью платформы.
Весь процесс – это инженерно выверенная последовательность шагов, где ИИ (LLM) используется как «интеллектуальное ядро», но строго направляется и контролируется нашей платформой. Ключевой принцип — итеративность и обратная связь от реального окружения. ИИ не просто пишет код «в стол», он сразу же запускает его на тестовом стенде, анализирует результаты ошибок и на их основе дорабатывает тест. Это превращает его в подобие опытного разработчика, который не только пишет код, но и отлаживает его.
Особенности Digital Q.DevOps, которые упростили контроль ИИ:
Использование Digital Q.Archer как единый источник правды: Поскольку все контракты API и событий хранятся в Digital Q.Archer, у нас есть эталонное описание того, как должны взаимодействовать сервисы. Оркестратор ИИ берет контракты именно оттуда, что исключает работу с устаревшей или неверной документацией.
Встроенная инфраструктура запуска: В Digital Q.DevOps уже есть сервисы для запуска автотестов на тестовых стендах. Агенту не приходится их создавать с нуля – он просто вызывает их по HTTP, передавая сгенерированный код и параметры подключения. Это позволило легко и безопасно дать ИИ возможность выполнять код в изолированном окружении (пода).
Доменные правила (Domain Rules): Мы научили Оркестратор проверять код теста на соответствие нашим внутренним стандартам (например, обязательное использование библиотечного класса SpecBase). Если тест не соответствует правилам, он отправляется ИИ на доработку с указанием, что именно нужно исправить.
Как это работает
Процесс состоит из четких шагов, где тестировщик и ИИ взаимодействуют через Оркестратор:
Старт: Тестировщик выбирает целевой тестируемый сервис (модель) и указывает тест-кейс на бизнес-языке.
Получение контрактов: Оркестратор по модели сервиса загружает Swagger (API) и JSON-схему событий, парсит и фильтрует их.
Отбор эндпоинтов и событий: Оркестратор отдает в LLM список отформатированных и отфильтрованных эндпоинтов и тест-кейс. LLM отбирает релевантные для сценария эндпоинты. Затем процесс повторяется для событий. Пользователь видит и может подтвердить отобранные сущности.
Генерация: Оркестратор передает в LLM список отобранных эндпоинтов и событий, тест-кейс и наши доменные правила. LLM генерирует код автотеста на Groovy.
Валидация кода: Оркестратор проверяет код на соответствие правилам (например, импорты, использование нужных базовых классов). Если есть ошибки, код возвращается в LLM на доработку с указанием причины.
Запуск и итеративная отладка: Оркестратор отправляет код в сервис запуска, который выполняет тест на реальном стенде. Результат (успех/неудача с логами) возвращается в Оркестратор. Если тест упал, Оркестратор снова отправляет в LLM код и ошибку для исправления. Этот цикл повторяется заданное число раз (RepeatTimes), пока тест не будет стабильно проходить. Обычно хватает 2-3 итераций.
Финальная обработка и публикация: После успешного прохождения Оркестратор добавляет в код служебную информацию (AI-лейбл, импорты, пакет), сохраняет статистику и коммитит готовый тест в Git-репозиторий продукта.
Язык кода автотеста
ИИ генерирует исполняемый код автотеста на Groovy. Groovy выбран как основной язык для тестов, так как он Java-подобный, а продукты в микросервисной архитектуре в Диасофт как раз создаются в основном на Java. При этом сама технология генерации не привязана жестко к языку – при необходимости мы можем адаптировать ее для Python или Java.
Отдельно про тестирование событий
Тестирование событий (асинхронного взаимодействия) сложнее, чем API. При вызове API мы сразу видим синхронный ответ. При работе с событиями нужно: 1) инициировать действие, которое породит событие; 2) «поймать» это событие в брокере сообщений; 3) проверить его структуру и содержимое. В нашем процессе ИИ справляется с этим благодаря тому, что на этапе отбора эндпойнтов и событий он получает формализованное описание событий (из того же Digital Q.Archer), а на этапе запуска и итеративной отладки сервис запуска автотестов уже умеет подписываться на нужные топики и валидировать пришедшие сообщения. ИИ генерирует код, который использует эти возможности инфраструктуры.
Как использование ИИ меняет подход к работе тестировщиков
С технической точки зрения происходит фундаментальный сдвиг: мы переходим от написания кода к управлению требованиями на языке бизнеса.
Что теперь делает тестировщик?
Готовит качественную инструкцию для ИИ (тест-кейс). Чем четче и детальнее сформулирован сценарий на бизнес-языке («Создать вклад, начислить проценты по ставке 5% и проверить, что итоговая сумма равна ...»), тем точнее и быстрее ИИ подберет нужные эндпоинты и сгенерирует корректный код. Это требует от тестировщика глубокого понимания продукта и умения формализовать бизнес-требования.
Верифицирует готовый автотест. Тестировщик превращается в «приемщика» работы ИИ. Ключевой вопрос теперь не «правильно ли написан код?», а «соответствует ли этот код исходному бизнес-сценарию?». Ответить на него может только специалист, который досконально знает логику работы продукта.
Советы по работе в новых условиях
При составлении тест-кейса:
Описывайте бизнес-процесс, а не последовательность нажатия кнопок в UI или вызовов API. Указывайте цели и ожидаемый бизнес-результат.
Используйте терминологию предметной области, понятную и бизнес-аналитику, и (как показывает практика) ИИ.
При проверке сгенерированного теста:
Сосредоточьтесь на логике проверок (assertions).
Убедитесь, правильно ли ИИ понял, что именно нужно проверить в ответе или в событии.
Выясните, достаточно ли этих проверок для подтверждения бизнес-сценария.
Не пытайтесь вычитывать код построчно – оценивайте его смысловое соответствие задаче.
ИИ не заменяет тестировщика, а снимает с него рутину по кодингу, позволяя сконцентрироваться на сути – глубоком анализе качества продукта с точки зрения бизнеса. Требования к квалификации становятся выше, но и ценность такой работы возрастает многократно.
Согласны с этим? Буду рада обсудить в комментариях.
Комментарии (6)

gl_uk
26.03.2026 20:421) работает ли оно в локально? Какие мощности требуются.
2) нигде не сказано что это за LLM - на чем она основана, какие лицензии? ФСТЕК и прочее?
3) вы каждый раз генерируете тесты? Зачем? Это большая и лишняя нагрузка - не логично ли агенту собирать уже готовый код?
4) примеры бы показать - у вас все в куче и развертывание и тесты и... Шаг 3-5, например, требует от QA глубокое знание архитектуры проекта. Не каждый программист обладает этими знаниями в проекте
5) кто контролирует агента от чуши?
Мой опыт показывает, что для агентов нужно писать отдельные строгие ограничения, прямо ему запрещающие ходить налево =) и то это не всегда работает. Как это у вас устроено?

diasoft Автор
26.03.2026 20:421) У нас развернуто внутри контура Диасофт.
2) На данный момент мы используем языковую модель Qwen3-30B-A3B, развернутую через vLLM. Это трансформерная LLM семейства Qwen (аналог GPT-подобных моделей), распространяемая с открытыми весами под лицензией Apache 2.0, что допускает коммерческое использование, модификацию и развертывание в инфраструктуре заказчика.
3) Тесты генерируются тестировщиком по мере необходимости при добавлении нового функционала. Мы автоматизировали процесс тестирования – если ранее при добавлении функционала пользователь писал тест каждый раз под новый функционал, теперь ему необходимо под этот новый функционал описать сценарий, а тест за него напишет LLM. Насчет анализа нового кода агентом напрямую без описания сценария пользователем, тут вопрос не в логичности, а в ограничении ресурсов. Анализ кодовой базы – процесс непростой, для этого необходимо использовать модели с сильно бОльшим контекстом.
В дальнейшем планируется развитие агента – одним из направлений развития как раз и является генерация пользовательского сценария по измененному коду с помощью LLM. В этом случае дальнейшая цепочка генерации теста не изменится, поменяется лишь способ получения исходного сценария (тест-кейса).
4) QA должен понимать какой функционал тестируется, какие входные и выходные данные для тестирования функционала должны использоваться. Глубокое понимание архитектуры проекта ему не требуется.
Пользователь, который подает на вход сценарий, подает его осознано, т.е. знает и понимает какие эндпоинты и для чего используются.
В качестве примера рассмотрим следующий кейс.
Пользователь задает сценарий в терминологии бизнеса: "Добавь тип суммы, поменяй у него название, удали его, проверь, что его больше нет #apionly"
ИИ как раз отбирает необходимые эндпоинты:
POST /agreement-amount-type
PUT / agreement-amount-type/{agreementAmountTypeld}
DELETE / agreement-amount-type/{agreementAmountTypeld}
GET / agreement-amount-types
Затем происходит генерация теста.
Если какие-то параметры не будут учтены в одном из вариантов автотестов, то тест не будет пройден, ИИ получит ошибку, прочитает ее и исправит тест относительно текста ошибки.
5) В промте у нас описаны правила построения автотеста, а также в некоторых инструкциях мы явно указываем, как делать не надо. Также от чуши спасает абстрагирование от деталей вызова API/события за счет использования заготовленных методов (определенных в Groovy-сервисе для запуска тестов). То есть LLM не нужно знать, как подключаться к брокеру или как звать API по REST. LLM использует заготовленные нами "кубики" и понимает, что в случае отбора API POST/api/request надо в тесте использовать метод clientPost(), а в случае отправки события и ожидания ответа – sendEventAndWaitForReply().
Дополнительно после отбора API/событий мы проверяем их наличие в документации. Если это результат фантазий LLM, то тест генерироваться не будет. Если LLM сильно фантазирует при генерации теста, то мы это пресекаем проверкой валидности теста при запуске – откровенная «чушь» успехом при запуске не завершится.

gl_uk
26.03.2026 20:42Спасибо за развернутый ответ!
Про контекст есть небольшой финт- если модели давать лишь формальное описание методов (без фанатизма, отвечающий на вопрос: что делает, что ему нужно, что получается) в виде небольшого списка, который модель тоже не хранит - а просто ходит за ним, то размер контекста сокращается в сотни раз.
greenfork
Сложность работы с ЛЛМ в том, что она может выдавать правдоподобный код, который содержит ошибки. Как отлавливаются логические ошибки в тестах, если их не вычитывают построчно? Например, по факту не происходит проверка заявленного тест кейса
diasoft Автор
Защита от логических ошибок в тестах происходит на нескольких уровнях:
1) После указания пользовательского сценария (заявленного тест-кейса) сначала происходит отбор API/событий по семантической близости с заявленным тест-кейсом. После этого отобранные API/события явно выводятся пользователю, и он может проваладировать корректность их отбора.
При этом дополнительно после отбора API/событий и ответа от LLM мы сопоставляем отобранные API/события с задокументированными. Если в документации такие API/события мы не находим, то тест далее не генерируется.
2) Наш Groovy-сервис, который запускает сгенерированные моделью тесты, включает в себя обертки для осуществления REST/асинхронных запросов. Мы определяем методы (clientPost(), clientGet(),sendEventAndWaitForReply()), которые скрывают детальную реализацию REST/асинхронного взаимодействия. Логика в методах детерминирована.
При обращении к LLM с просьбой составить тест мы передаем системный промпт, в котором четко регламентируем структуру теста с примерами – явно указываем, какие методы разрешено использовать (наши высокоуровневые – clientPost(), clientGet(), sendEventAndWaitForReply()). То есть мы снимаем с модели нагрузку на продумывание детальной реализации отправки POST запроса или взаимодействия с брокером – это мы берем на себя, а модели нужно лишь позвать нужные "кубики".
3) Помимо этого, результаты работы модели выводятся в чат, и пользователь может наблюдать за процессом генерации теста. Пользователю виден тест на каждой итерации генерации, виден лог после запуска теста – при анализе теста он видит какие "кубики" использовались и входные параметры, которые LLM посчитала нужным проставить. После запуска теста в логах он видит результат вызова API/отправки/получения события – выходные параметры выводятся в лог.
greenfork
1) То есть тестер после генерации ответственен просмотреть все тест кейсы и соответствующие API события. Надо какое-то конкретное действие сделать, чтобы одобрить генерацию?
3) У вас получается на все события отправка/получение стоят логи? На вызов методов/функций тоже ставите логи или внутри одного сервиса взаимодействие без логов идёт?