Как мы построили AI-экзоскелет для QA-инженера: от идеи до 11 автономных агентов

Как мы построили AI-экзоскелет для QA-инженера: от идеи до 11 автономных агентов

Тестирование «отстаёт» от разработки, автотесты не успевают за сценариями, а увеличение бюджета на QA ситуацию не спасает. Знакомо?

Привет! Меня зовут Михаил Федоров, я руковожу центром компетенций QA. Мы решили не нанимать ещё двух тестировщиков, а написать систему AI-агентов, которая берёт на себя 80% рутины QA-инженера — от анализа требований до Merge Request с готовыми автотестами. В этой статье расскажу, как устроена архитектура, какие грабли мы собрали и что из этого вышло на практике.

1. Проблема: почему тестирование буксует

Представьте типичную ситуацию. Разработка выкатывает фичу, QA-инженер садится писать тест-кейсы, параллельно разбирается в требованиях, заводит их в TMS, готовит тестовые данные, пишет автотесты… А к этому моменту разработка уже выкатила следующую фичу. Автотесты не дописаны, приходится быстро проверять руками, пропускать менее приоритетные виды проверок. Тест-кейсы пишутся в формате чеклистов — на подробные сценарии с шагами времени нет. Ротация тестировщика — катастрофа: на погружение нужен месяц минимум. Подключение автоматизатора — тоже проблема: сначала нужно детализировать сценарии, чтобы он хоть что-то понял из чеклистов. В итоге ручной регресс растёт от спринта к спринту.

Мы проанализировали, на что уходит время QA-инженера:

До 80% времени инженера уходит на задачи, которые поддаются систематизации и автоматизации. При этом:

  • С ростом сложности продукта растёт число багов
  • Автотесты «не успевают» за доработками сценариев, растёт время регресса
  • Сложно понять, что именно проверяют автотесты и насколько оптимально покрытие
  • С ростом бюджета на QA ситуация принципиально не меняется

Нам нужно было не просто ускорить отдельные этапы, а перестроить весь процесс — от получения требований до готового отчёта.

2. Идея: QA-инженер как оператор AI-ассистента

Мы сформулировали концепцию так: QA-инженер не заменяется, а усиливается. Как экзоскелет умножает физическую силу, так AI-ассистент умножает продуктивность инженера.

Что изменилось в роли инженера

  • Инженер лично выполняет каждый этап тестирования
  • Каждый использует свой набор промптов и инструментов
  • Ручное управление тестовыми данными, ручной тест-дизайн
  • Формат результата не учитывает дальнейший жизненный цикл
  • Инженер определяет правила работы ассистента, руководствуясь корпоративной стратегией
  • Инженер ставит задачи ассистенту
  • Инженер контролирует качество артефактов на каждом этапе
  • Инженер корректирует результат при необходимости

Ключевые принципы

  1. Ассистент не требует глобальных изменений — он подстраивается под ваш стек. Привычные TMS, Task-tracker, язык автоматизации, CI/CD — всё остаётся прежним.
  2. Прозрачность — все артефакты генерируются в привычных форматах. Сценарии и отчёты в Zephyr, автотесты на pytest. Инженер всегда видит, что происходит.
  3. Полный контроль — возможность аудита ассистента на любом этапе. Чёткие зоны ответственности.
  4. Масштабируемость — один QA может управлять несколькими проектами. Легко прогнозировать рост трат при масштабировании с сохранением стандартного уровня качества.

3. Архитектура: 11 скиллов, один пайплайн

Система построена на базе Claude Code Skills — модульной системе агентов, где каждый скилл отвечает за свой этап QA-процесса.

11 скиллов системы

jira-fetch — загрузка задач из Jira/Confluence. Вход: URL задачи. Выход: Markdown + вложения.

requirements-decomposer — декомпозиция на User Stories и Tasks. Вход: требования. Выход: структурированные US/Task.

scenarios-generator — генерация тестовых сценариев по ISTQB. Вход: требования + Figma. Выход: JSON-сценарии + RTM.

scenario-data-fix — сбор недостающих тестовых данных. Вход: сценарии + Global Context. Выход: обновлённые сценарии.

scenario-discrepancies-fix — исправление расхождений с UI/API. Вход: ERRORS_DISCREPANCIES.md. Выход: исправленные сценарии.

selectors-collector — сбор CSS/Playwright селекторов из DOM. Вход: DOM. Выход: SELECTORS.json (POM).

automation-api — генерация pytest + requests. Вход: JSON-сценарии. Выход: готовый проект автотестов.

automation-ui — генерация pytest + Playwright. Вход: JSON-сценарии + SELECTORS.json. Выход: готовый проект UI-тестов.

automation-compare — сверка сценариев с автотестами. Вход: JSON + pytest-код. Выход: COMPARISON_REPORT.md.

zephyr-uploader — загрузка тест-кейсов в Zephyr Scale. Вход: JSON-сценарии. Выход: кейсы в TMS.

mr-creator — создание Merge Request в GitLab. Вход: готовые автотесты. Выход: MR в целевом репозитории.

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

4. Подробнее о каждом этапе

4.1. Загрузка и анализ требований

Всё начинается с URL Jira-задачи. Скилл jira-fetch через REST API вытягивает:

  • Описание задачи и поля
  • Вложения (PDF, DOCX, XLSX, PPTX) — автоматически скачиваются и парсятся
  • Подзадачи рекурсивно
  • Данные из связанных страниц Confluence

Важно, что входные данные не обязаны следовать какой-то жёсткой структуре — задача может быть оформлена как угодно: свободным текстом, таблицами, вложенными документами. Главное, чтобы требования были полными по содержанию. Всё остальное система разберёт сама.

Затем requirements-decomposer декомпозирует всё это в структурированные документы. Для этого этапа мы совместно с отделом аналитики проработали специальные шаблоны декомпозиции, которые учитывают принятые в компании стандарты описания User Stories и Tasks. Это обеспечивает единообразие артефактов независимо от формата исходных требований.

На каждом уровне — будь то User Story или задача на разработку компонента — формируются функциональные требования, нефункциональные требования и критерии приёмки. Требования декомпозированы до атомарных проверок, и именно с ними идёт основная работа на всех последующих этапах.

Здесь же автоматически подгружается Global Context — централизованное хранилище знаний о проекте (API-контракты, эндпоинты, тестовые данные, архитектура). Это позволяет генерировать сценарии с учётом реального окружения, а не в вакууме.

4.2. Генерация тестовых сценариев

Это ключевой этап. Тест-дизайн строится в соответствии с пирамидой тестирования: на уровне User Story генерируются e2e-сценарии, покрывающие сквозные пользовательские пути, а на уровне компонентных задач — изолированные тесты отдельных модулей (API-эндпоинтов, UI-форм).

scenarios-generator применяет техники тест-дизайна по ISTQB автоматически:

  • Эквивалентное разбиение — группировка входных данных в классы
  • Анализ граничных значений — тестирование пределов (min, max, off-by-one)
  • Таблицы решений — комбинаторное тестирование сложных условий
  • Переходы состояний — многошаговые пользовательские сценарии

Каждый сценарий генерируется в строгом JSON-формате с полной трассируемостью.

Параллельно формируется Requirements Traceability Matrix (RTM) — матрица покрытия требований тестами. Она показывает, какой процент требований покрыт сценариями.

4.3. Интеграция с Figma (MCP)

Для фронтенд-задач система подключается к Figma через Model Context Protocol (MCP). Это не просто скриншоты — мы анализируем структуру макетов:

  • Извлекаем UI-элементы, текст, состояния и ограничения
  • Определяем расхождения между требованиями и дизайном
  • Выявляем неочевидные кейсы (например, дизайн показывает, что кнопка скрыта, а не задизейблена — это разные тест-кейсы)

Результаты сохраняются в FIGMA_DATA.json и автоматически учитываются при генерации UI-сценариев.

4.4. Автоматизация: API и UI тесты

Генератор API-тестов (automation-api) создаёт полностью автономный pytest-проект.

Аналогично работает automation-ui, но с Playwright и использованием собранных DOM-селекторов.

Важный момент — четырёхфазный пайплайн автоматизации:

  1. Setup: загрузка контекста, API-контрактов, тестовых данных
  2. Генерация кода: создание pytest-файлов из JSON-сценариев
  3. Отладка — состоит из двух этапов (подробнее ниже)
  4. Отчёты: маркировка тестов (pass/skip/xfail), генерация DEBUG_REPORT.md

4.5. Отладка автотестов

Отладка состоит из двух этапов.

Этап 1 — функциональная отладка. Каждый тест запускается индивидуально. Ошибки классифицируются: баг в коде теста (опечатка, неверный эндпоинт, неправильные данные) или реальный дефект системы. Баги кода исправляются автоматически, реальные дефекты маркируются как xfail. Для UI-тестов на этом же этапе подбираются и уточняются селекторы элементов через отдельный скилл selectors-collector.

Этап 2 — мутационное тестирование. После того как тест прошёл, мы инвертируем его assert’ы. Если мутированный тест тоже проходит — значит, оригинальный тест ничего не проверяет. Это позволяет отсеять «пустые» тесты, которые создают иллюзию покрытия.

4.6. Обработка расхождений

На протяжении всего пайплайна скиллы фиксируют расхождения между источниками данных: требования говорят одно, Figma показывает другое, а реальный интерфейс ведет себя по-третьему. Все такие расхождения записываются в единый протокол — ERRORS_DISCREPANCIES.md. Скилл discrepancies-fix обрабатывает этот протокол, классифицирует каждый пункт и контролирует его статус.

В авто-режиме работает иерархия приоритетов источников: Jira > Figma > Требования > Тестовые сценарии > Реализация. Расхождения, где приоритет однозначен, закрываются автоматически. Остальные — выносятся на решение инженера.

Пример автоматического закрытия. В требованиях написано: «Показать текст: При удалении папки мы перенесем все чаты в архив. Удалить папку?» — одной фразой. В Figma — заголовок «Удалить папку?» и отдельный текст «При удалении папки мы перенесем все чаты в архив». Тип расхождения — FIGMA_REQ_MISMATCH. Figma имеет приоритет над текстовыми требованиями для UI-элементов, поэтому сценарий обновляется автоматически.

Пример обработки бага. Backend должен возвращать 400 при имени домена длиннее 50 символов, но реально возвращает 201 Created. Тип — BUG_MISSING_VALIDATION. Это реальный дефект, и автоматически его закрыть нельзя. Скилл перепроверяет воспроизводимость, оформляет баг-репорт и запрашивает у инженера разрешение на создание дефекта в Jira. После подтверждения — создаёт тикет и маркирует затронутые тесты как xfail с привязкой к нему.

4.7. Доставка результатов

На финальном этапе:

  • zephyr-uploader загружает тест-кейсы в Zephyr Scale через ATM API, с правильными приоритетами, тегами и привязкой к проекту. После загрузки маркирует автотесты ключами Zephyr для связи между кодом и TMS
  • mr-creator клонирует целевой репозиторий автотестов, создаёт feature-ветку, анализирует совместимость (конфликты фикстур, зависимости, .env), копирует файлы и создаёт Merge Request через GitLab API

5. Оркестрация: мульти-агентное параллельное выполнение

Оркестратор — это координатор, который управляет всем пайплайном. Он никогда не выполняет скиллы сам — вся работа делегируется субагентам через Task API.

Ключевые задачи оркестратора:

  • Точка входа для инженера — всегда может объяснить текущий статус задачи, что уже сделано и что осталось
  • Контроль соблюдения этапов — гарантирует правильную последовательность выполнения и не пропускает шаги
  • Контроль качества артефактов — валидирует выходные данные каждого этапа перед передачей на следующий
  • Ускорение пайплайна — распараллеливает независимые задачи между агентами

Режимы выполнения

single_skill — N агентов работают над одним скиллом. Например: 3 агента генерируют API-тесты параллельно.

parallel_types — API и UI автоматизация параллельно. Например: два агента одновременно пишут API и UI тесты.

batch_issues — обработка нескольких задач. Например: DEVAI-258 и DEVAI-259 одновременно.

Полный цикл с зависимостями — Jira → сценарии → автотесты → MR.

Контрольные точки (Quality Gates)

Оркестратор проверяет качество на каждом этапе. Например, после генерации сценариев проверяется:

  • Корректность JSON-схемы
  • Наличие трассируемости требований
  • Полнота покрытия (по RTM)
  • Наличие и заполненность шагов
  • Разметка приоритетов
  • Отсутствие дублирования

После автоматизации — ещё более строгая проверка: 14+ контрольных точек для API и 16+ для UI, включая валидацию синтаксиса Python-кода, запуск тестов, проверку фикстур.

6. Интеграции: Jira, Figma, Zephyr, GitLab

Что подключается и как используется

Jira — загрузка задач, подзадач, вложений.

Confluence — загрузка спецификаций.

Figma — анализ UI-макетов через MCP.

Zephyr Scale — загрузка тест-кейсов через ATM REST API.

GitLab — создание MR с автотестами через REST API + Git.

Playwright — сбор селекторов, UI-тестирование через Browser Automation.

Корпоративный Global Context

Централизованное хранилище знаний о проекте:

  • API-контракты (OpenAPI)
  • Эндпоинты и примеры запросов
  • Тестовые данные (аккаунты, токены, домены)
  • Архитектура системы
  • Правила именования, стек технологий

Это позволяет каждому скиллу работать с реальным контекстом проекта, а не генерировать абстрактные тесты.

7. Технические решения и грабли

Решение 1: Минимальный стек для пилота

Для пилотной версии мы сознательно выбрали максимально простой стек: Claude Code и его нативные агенты. Никаких дополнительных фреймворков для оркестрации, очередей сообщений или кастомных рантаймов. Вся логика скиллов, координация агентов и интеграции реализованы средствами платформы. Это позволило сосредоточиться на бизнес-логике QA-процесса, а не на инфраструктуре.

Решение 2: JSON-сценарии как единый источник правды

Вместо того чтобы позволить тест-кейсам и автотестам расходиться (классическая проблема), мы сделали JSON-сценарии центральным элементом.

Скилл automation-compare сверяет код обратно с JSON: анализирует каждый шаг каждого тест-кейса и проверяет, как именно он реализован в pytest-коде. На выходе — метрика процента соответствия между сценариями и автотестами. Если соответствие ниже порога, расхождения автоматически исправляются. Это обеспечивает синхронизацию на протяжении всего пайплайна.

Решение 3: Идемпотентность операций

Каждый скилл можно безопасно перезапустить:

  • selectors-collector обновляет только невалидированные селекторы
  • discrepancies-fix пропускает уже закрытые пункты
  • mr-creator при повторном запуске определяет, что ветка существует, и делает инкрементальное обновление

Решение 4: Авто-режим для рутинных решений

Многие скиллы поддерживают флаг --auto:

  • discrepancies-fix --auto — автоматически закрывает очевидные расхождения по правилам приоритетов, оставляя неоднозначные для ручного разбора
  • data-fix --auto — сначала пытается найти данные в Global Context, спрашивает только по оставшимся пунктам

Это сокращает количество точек, где нужно вмешательство человека, при этом сохраняя контроль над неоднозначными решениями.

Грабли 1: Контекстное окно LLM

Организация работы с контекстным окном — один из ключевых моментов для получения хорошего результата. Причём проблема не только в переполнении: даже приближение к максимально допустимому объёму уже приводит к снижению качества ответа. Модель начинает «забывать» нюансы сложных промптов, пропускать детали, упрощать логику. Когда у вас задача с множеством API-контрактов и Figma-данными, всё это физически не помещается в один промпт без потери качества.

Решение: мы дробим задачи в двух измерениях. По горизонтали — декомпозиция требований: большая задача разбивается на User Stories и подзадачи с независимыми требованиями, каждая из которых помещается в свой контекст. По вертикали — разделение пайплайна на независимые этапы с чёткими input/output контрактами: каждый скилл получает ровно тот контекст, который нужен для его работы, а Global Context загружается частично, по запросу. В итоге система решает много мелких задач и объединяет результат.

Грабли 2: Галлюцинации при генерации тестов

LLM иногда «придумывает» несуществующие API-эндпоинты или параметры запросов.

Решение: интеграция с корпоративным Global Context (OpenAPI-спецификации, реальные эндпоинты). Генератор работает не в вакууме, а с привязкой к реальным контрактам. Плюс мутационное тестирование отлавливает тесты, которые проходят по случайности.

Отдельная история — нежелательное поведение модели, которое лечится точечными фиксами в промптах скиллов. Написать автотест без assert, проигнорировать нефункциональные требования, пропустить негативный сценарий — модель может ошибаться там, где не ждёшь. Мы постоянно отслеживаем результат и фиксим обнаруженные проблемы. Это непрерывный процесс, а не разовая настройка.

Грабли 3: Параллельное выполнение агентов

Когда несколько агентов работают одновременно, возникают конфликты: доступ к файлам, перезапись результатов, гонки состояний.

Решение: оркестратор изолирует рабочие пространства агентов и использует checkpoint-валидацию между этапами. Агент не начинает работу, пока не подтверждено качество артефактов предыдущего этапа.

Грабли 4: Ограничения платформы

Субагенты в Claude Code — экспериментальная функция со своими особенностями. Например, субагент безвозвратно завершается при достижении часового лимита на токены, и оркестратор должен это корректно обработать. Из-за бага субагенты некорректно работают с MCP-серверами (в частности с Figma), что приходится обходить на уровне архитектуры скиллов. Платформа активно развивается, и часть ограничений со временем уходит, но нужно быть готовым к тому, что инструмент ещё сырой.

8. Результаты и метрики

Что получаем на выходе

На входе — ссылка на Jira-задачу. На выходе:

  • Структурированные требования (User Stories + Tasks)
  • JSON-сценарии с полной трассируемостью
  • Матрица покрытия требований (RTM)
  • Готовый проект API-автотестов (pytest + requests)
  • Готовый проект UI-автотестов (pytest + Playwright)
  • Тест-кейсы в Zephyr Scale
  • Merge Request в целевом репозитории автотестов
  • Отчёты о качестве и расхождениях

Результаты за 1.5 месяца пилота

Регрессионных тест-кейсов: было — абстрактная детализация, не хватало времени на подробности; стало — максимально подробная, каждый шаг с данными и ожидаемым результатом.

Автоматизация: было — отсутствовала; стало — ~100% покрытие регресса.

Время регресса: было — десятки минут; стало — секунды.

Время от завершения разработки до апрува QA: было — несколько дней; стало — несколько часов.

Подключение тестирования на новый проект: было — найм + адаптация (месяцы); стало — ~4 часа настройки, первые баги уже в бэклоге.

Обнаруженные противоречия в требованиях + баги: 10+, система замечает нюансы, которые сложно уловить вручную.

Сравнение «было/стало»

Анализ требований: было — ручная подгрузка, свои промпты; стало — автоматический сбор контекста по задачам.

Тест-дизайн: было — ручной, у каждого свой подход; стало — единые шаблоны на базе стратегии QA.

Тестовые данные: было — ручное управление; стало — генерация из корпоративных источников.

Создание кейсов в TMS: было — ручной ввод; стало — автоматический импорт.

Автоматизация: было — ручная подготовка к автоматизации; стало — сценарии сразу генерируются с учётом автоматизации.

Тестирование новой фичи: было — руками, т.к. автоматизация дорога; стало — автотесты готовы к завершению разработки.

Главное — теперь процесс тестирования это чётко структурированный пайплайн с понятным результатом и возможностью тонкой настройки под проект в соответствии с выбранной стратегией. Хотите внедрить pixel-perfect тестирование? Исследовательские тесты? Расширить нефункциональное покрытие? Добавить поддержку нового протокола или интеграцию со своей TMS? Всё гибко и решаемо — достаточно добавить или доработать соответствующий скилл.

Пилотная версия работает на подписке Claude Pro ($100/мес). Этого хватает для поддержки 2–3 проектов с объёмом около 100+ тестов в месяц на проект.

9. Чему мы научились

1. Модульность — ключ к развитию

Каждый скилл — это отдельный, самодостаточный агент с чёткими входами и выходами. Это позволяет:

  • Разрабатывать и тестировать скиллы независимо
  • Запускать параллельно через оркестратор
  • Заменять или дорабатывать отдельные этапы, не трогая остальные

2. Global Context решает проблему галлюцинаций

Централизованное хранилище знаний о проекте — это не просто удобство. Это необходимость для работы с LLM. Без контекста модель генерирует правдоподобный, но бесполезный код. С контекстом — рабочие тесты, привязанные к реальным эндпоинтам и данным.

3. Качество важнее скорости

На каждом этапе пайплайна стоит checkpoint-валидация. Это замедляет процесс, но предотвращает «каскад ошибок», когда некачественные артефакты одного этапа порождают мусор на следующем.

4. Авто-режим + ручной контроль = баланс

Полная автоматизация невозможна (и не нужна). Лучшая стратегия — автоматизировать очевидное и оставить человеку неоднозначные решения. Флаг --auto сначала закрывает всё, что может, а остальное предлагает на рассмотрение.

5. Инвестируйте в сбор контекста

LLM не сделает чуда, но он способен качественно проработать все поданные на вход данные. Если требования были описаны — они точно будут покрыты тестами. Но если у вас принято писать только заголовки в Jira-задачах, то сначала нужно поработать над процессами в команде. Качество результата напрямую зависит от качества входных данных.

10. Что дальше

Развитие функциональности

Идей для улучшения — больше, чем рук. Вот основные направления:

  • Расширение стека — сейчас система работает с Web + REST API, впереди поддержка SOAP, gRPC, GraphQL, мобильных приложений
  • Умный мёржинг в регресс — автоматическое встраивание новых тестов в существующую регрессионную модель с учётом приоритетов и зависимостей
  • Покрытие старой функциональности — генерация тестов не только для новых фич, но и для уже существующего функционала, где покрытие недостаточно
  • Работа с дефектами — полный цикл: обнаружение, классификация, создание в Jira, отслеживание статуса, автоматическое снятие xfail после фикса

Путь к SaaS

Реализация на Claude Code отлично подошла для пилота: минимальный стек, быстрый старт, возможность итеративно отлаживать каждый скилл. Но для полноценного продукта нужен другой уровень — управление пользователями, мониторинг, биллинг, стабильная работа без ограничений CLI. Поэтому мы уже смотрим в сторону создания самостоятельного продукта — многопользовательского веб-сервиса с:

  • Веб-интерфейсом для управления пайплайнами (React)
  • Асинхронной обработкой через Temporal
  • Multi-tenancy с изоляцией данных (PostgreSQL RLS)
  • Системой подписки и usage-based billing (Stripe)
  • Интеграцией с Claude Agent SDK для управления агентами

Безопасность данных

Мы понимаем, что безопасность — краеугольный камень при работе с внешними LLM. В рамках пилота контроль чувствительных данных лежит в зоне ответственности пользователей: инженер сам решает, какие данные попадают в контекст. Но для продуктового решения этого недостаточно, и мы прорабатываем варианты:

  • Маскирование данных — автоматическая замена чувствительных значений (токены, пароли, персональные данные) перед отправкой в LLM и восстановление в результатах
  • On-premise LLM — возможность развёртывания с локальными моделями, когда данные не покидают контур компании
  • Политики доступа — гранулярное управление тем, какие проекты, репозитории и данные доступны каждому пользователю
  • Аудит-лог — полная запись всех запросов к LLM для контроля и compliance

Заключение

Так уволят ли завтра всех тестировщиков? Мы проверили на практике и вот что поняли:

QA Assist — это не замена тестировщика. Это инструмент, который превращает QA-инженера из исполнителя рутинных задач в оператора, управляющего AI-агентами. Инженер принимает ключевые решения, определяет стратегию, контролирует качество — а система выполняет объём работы, который раньше требовал целой команды.

Мы не пытались создать «чёрный ящик», который магически выдаёт автотесты. Мы построили прозрачный, контролируемый пайплайн с чёткими промежуточными результатами на каждом этапе. И именно эта прозрачность позволяет доверять результату.

Использование AI безусловно станет корпоративным стандартом на горизонте нескольких лет. Но глубокая экспертиза в тестировании будет востребована всегда — именно она определяет, чему учить ассистента и как оценивать его результат.

Читать оригинал