ESPN DeportesCR7 pide suspender a fans por burlas a Diogo JotaRTP DesportoEuroVolley 2026. Portugal soma quarta derrota consecutiva frente à UcrâniaESPN'I'm willing to do whatever it takes': Inside the 274 days that rebuilt Patrick MahomesThe Jerusalem PostUS President Donald Trump shares his music taste with reporters in odd exchange on Air Force OnePunchNASEMA distributes relief materials to disaster, banditry victimsInquirerSenate approves on 3rd reading 5-year term of barangay, SK officials3DNewsИлон Маск помирился с Apple — но X Corp и SpaceXAI продолжат судиться с OpenAIBusiness AMDenemarken en VS streven naar diplomatieke oplossing voor geschil over GroenlandRapplerLIVE UPDATES: First BARMM parliamentary electionsAntara NewsChinese hiker injured on Indonesia's Mount Rinjani, SAR team deployedBillboardMacklemore Dropped From Ed Sheeran Tour Over His ‘Free Palestine’ CommentsCNN بالعربية"لكن أنا الذي أستحقها".. لامين يامال يسمّى منافسه الوحيد في سباق الكرة الذهبية 2026
The Daily Newsstand · Free, Always
Monday, September 14, 2026

AI‑агент вместо ручного регресса: архитектура, метрики, инсайты

Translate

Привет, Хабр! На связи Владимир Бойко, ведущий iOS‑разработчик в Т‑Банке. В статье расскажу, как мы построили AI‑QA‑агента, который проходит тест‑кейсы так же, как это делает человек: запускает приложение на симуляторе, выполняет сценарий шаг за шагом, анализирует экраны с помощью VLM и автоматически сравнивает ожидаемый результат с фактическим.

Идея родилась из бытовой боли. В нашем мобильном приложении десятки тысяч тест‑кейсов, регресс проводится дважды в месяц, и каждый цикл съедает значительную часть ресурсов QA‑команд. Во время регресса QA фактически недоступны для остальных задач. А с учетом санкционных ограничений окна для релизов ограничены и цена пропущенного дефекта возрастает: следующий шанс исправить может появиться не скоро.

Примерно в то же время я заканчивал задачи с VLM для Умной камеры и плотно общался с командой VLM Core — ребятами, которые развивают инфраструктуру мультимодальных моделей внутри банка. Вопрос напрашивался сам собой: а что если агент на базе VLM сможет выполнять эти проверки вместо людей?

Ограничения существующих подходов

Зачем писать агента, если есть ручное тестирование, E2E‑тесты, Snapshot‑тесты? У каждого из них есть свои ограничения.

Ручное тестирование не масштабируется. Чем больше продукт, тем больше сценариев, а количество QA‑инженеров не растет пропорционально. При этом ручной регресс — рутина, которая снижает концентрацию внимания и отвлекает от более ценной работы: исследовательского тестирования, анализа рисков, проработки тест‑дизайна.

E2E‑автотесты решают проблему масштабирования, но создают свою: высокий порог входа в написание и поддержку, хрупкость при изменениях UI, необходимость в инфраструктуре. Не каждая команда может позволить себе выделить ресурсы на полноценную автоматизацию — особенно когда фичи выпускаются быстрее, чем пишутся тесты.

Snapshot‑тесты хороши для пиксельных регрессий, но не проверяют пользовательские сценарии и плохо работают с динамическим контентом.

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

Мы подумали, что можно попробовать заменить в ручном тестировании человека на AI и так решить проблемы ограниченного времени, усталости и невозможности масштабироваться

Обзор решения

Прежде чем погружаться в детали реализации, покажу общую картину.

В новом воркфлоу QA работает с тестами через нашу платформу Allure, где:

  • актуализирует пул тестовых пользователей;

  • выбирает тесты для прогона;

  • нажимает «запустить»;

  • ждет отчета и смотрит результаты.

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

Со стороны QA все выглядит просто. Но за этой простотой — система из нескольких компонентов, каждый из которых решает свою задачу. Расскажу про них и про решения, которые оказались неочевидными.

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

Руки агента — tap, swipe, scroll. Для управления симулятором я начал с существующих на рынке решений.

Первым кандидатом был idb. После первых тестов стало ясно, что стабильности не хватает: свайпы не отрабатывали, тапы срабатывали не с первой попытки, а на GitHub Issues полноценных ответов на эти проблемы не нашлось.

Следующим был WebDriver от Appium — фактически индустриальный стандарт. Но для наших задач оказался избыточен: это мощный комбайн с огромной кодовой базой, который нужно собирать, настраивать и поддерживать. Нам же нужен был легкий инструмент с конкретным набором функций.

В итоге я написал собственный навигационный движок на Swift. Он легковесный и содержит только те функции, которые нужны агенту: тапы, свайпы, ввод текста, скриншоты, управление состоянием симулятора. 

import XCTest


/// Командный мост: читает поток JSON-команд от Python-агента
/// и выполняет соответствующее действие над приложением в симуляторе.
final class NavigationEngine {
    private var app: XCUIApplication?


    func handle(_ command: Command) async throws {
        switch command.action {
        case .tap:
            // Координаты тапа приходят как строки, приводим к числовому виду.
            let x = command.args["x"] ?? "0"
            let y = command.args["y"] ?? "0"
            try tap(at: CGPoint(x: Double(x) ?? 0,
                                y: Double(y) ?? 0))


        case .swipe:
            // Жест задается начальной и конечной точкой (в device points).
            let x0 = Double(command.args["x_start"] ?? "") ?? 0
            let y0 = Double(command.args["y_start"] ?? "") ?? 0
            let x1 = Double(command.args["x_end"] ?? "") ?? 0
            let y1 = Double(command.args["y_end"] ?? "") ?? 0
            try swipe(from: CGPoint(x: x0, y: y0),
                      to:   CGPoint(x: x1, y: y1))


        case .type:
            // Ввод текста: координата поля + сам текст.
            try await enterText(text: command.args["text"] ?? "",
                                at: command.args["point"] ?? "0,0")
        }
    }


    /// Тап в точку экрана: из координаты строим XCUI-координату и тапаем.
    private func tap(at point: CGPoint) throws {
        guard let app else { throw EngineError.noApp }
        let start = app.coordinate(withNormalizedOffset: .zero)
        start.withOffset(CGVector(dx: point.x, dy: point.y)).tap()
    }


    /// Свайп из одной точки в другую (короткий press + drag).
    private func swipe(from startPoint: CGPoint, to endPoint: CGPoint) throws {
        guard let app else { throw EngineError.noApp }
        let root = app.coordinate(withNormalizedOffset: .zero)
        let start = root.withOffset(CGVector(dx: startPoint.x, dy: startPoint.y))
        let end   = root.withOffset(CGVector(dx: endPoint.x,   dy: endPoint.y))
        start.press(forDuration: 0.05, thenDragTo: end)
    }


    /// Ввод текста: кликаем по полю (вызываем фокус), затем печатаем текст.
    private func enterText(text: String, at pointString: String) async throws {
        guard let app else { throw EngineError.noApp }
        try tap(at: parsePoint(pointString))
        // Находим активное текстовое поле и вводим текст.
        if let field = app.textFields.firstMatch /* активное поле */ {
            field.typeText(text)
        }
    }
}


/// Описание одной команды, приходящей от Python-агента.
struct Command: Codable {
    enum Action: String, Codable { case tap, swipe, type }
    let action: Action
    let args: [String: String]
}

Код навигационного движка: Python‑агент присылает JSON‑команду, Swift‑обвязка над XCUITest диспатчит ее в конкретное действие над симулятором.

Работает стабильно, а благодаря тому, что это наш код, мы полностью контролируем поведение и можем быстро добавлять новые возможности. Основа — это XCUITest плюс наши обвязки для действий. Концептуальный принцип работы такой же, как и в WebDriver или idb.

Важный момент — кросс‑платформенность. Управление iOS‑симулятором и Android‑эмулятором различается: разные инструменты, разные возможности, разные ограничения. Например, смену темы на iOS можно сделать одной командой из CLI, а на Android такой возможности нет — нужен другой путь. Чтобы агент не знал об этих различиях, мы вынесли платформенные реализации за абстрактный интерфейс. Агент работает с единым набором команд: «нажми», «свайпни», «сделай скриншот».

Как именно выполняются команды на конкретной платформе, решает интерактор под капотом. Концептуально — обычный adb плюс avdmanager для взаимодействия с эмулятором и обертка над UIAutomator. Сейчас мы активно переходим на MCP и ACP, чтобы упростить взаимодействие с различными платформами и реализовать возможности интеграции агента в другие системы.

# Абстрактный интерфейс платформы (Python).
# Агент оперирует ТОЛЬКО этими методами — не зная, работает ли он с iOS-симулятором,
# Android-эмулятором или будущей MCP-обвязкой. Реализацию подставляет фабрика.


class PlatformDriver(Protocol):
    """Минимальный набор возможностей, нужных агенту для жизни."""


    # --- Связь и здоровье ---
    def health_check(self) -> bool: ...


    def restart_app(self) -> bool:
        """Атомарный перезапуск приложения (terminate + launch)."""
        ...


    # --- Действия ---
    def take_screenshot(self) -> str:
        """Скриншот текущего экрана — основа для VLM-анализа."""
        ...


    def open_deeplink(self, url: str) -> bool: ...


    def change_appearance(self, mode: str) -> bool:
        """Переключение светлой/темной темы (на iOS это одна команда CLI,
        на Android — другой путь; агенту это неважно)."""
        ...


    def get_accessibility_snapshot(self) -> list[dict]:
        """Дерево доступности экрана (label, type, frame, isEnabled…).
        Используется для датасетов и диагностики, а не для принятия решений."""
        ...

Глаза и мозг агента — VLM. Ключевой вопрос — как агент понимает, что сейчас происходит на экране. 

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

func getAccessibilitySnapshot() throws -> [[String: Any]] {
    guard let app else { throw EngineError.noApp }
    guard app.state != .notRunning else { throw EngineError.notRunning }

    var elements: [[String: Any]] = []
    var seen: Set<String> = []   // ключ дедупликации

    // 1) Рекурсивный обход полного снапшота.
    let snapshot = try app.snapshot()
    flattenSnapshot(snapshot, into: &elements, seen: &seen)

    // 2) Тип-специфичные запросы: покрывают агрегированные контейнеры
    //    (TabBar, виджеты), которые в снапшоте могут быть свернуты.
    for (type, typeName) in [
        (.button, "Button"), (.staticText, "StaticText"),
        (.textField, "TextField"), (.secureTextField, "SecureTextField"),
        (.cell, "Cell"), (.switch, "Switch"),
    ] {
        for element in app.descendants(matching: type).allElementsBoundByIndex
        where element.exists {
            addElement(element, typeName: typeName, into: &elements, seen: &seen)
        }
    }
    return elements
}

private func addElement(
    _ element: XCUIElement,
    typeName: String,
    into elements: inout [[String: Any]],
    seen: inout Set<String>
) {
    let frame = element.frame
    // NaN-значения нормализуем в 0, чтобы JSON не ломался.
    let key = "\(typeName)|\(frame.origin.x)|\(frame.origin.y)|\(frame.width)|\(frame.height)|\(element.label)"
    guard seen.insert(key).inserted else { return }

    elements.append([
        "label": element.label,
        "type": typeName,
        "frame": ["x": frame.origin.x, "y": frame.origin.y,
                  "w": frame.width,   "h": frame.height],
        "isEnabled": element.isEnabled,
        "isHittable": element.isHittable,
    ])
}

Извлекать Accessibility‑снапшот мы умеем: проходим дерево XCUITest и собираем плоские записи об элементах. Но для принятия решений этого недостаточно — в боевом сценарии делаем опору на VLM, а не на дерево

Все примеры из интернета демонстрируются на нативных приложениях Apple (Notes, Calendar, Safari) или простых приложениях из двух‑трех экранов. В нашем приложении сотни экранов и компонентов и далеко не все покрыты качественной accessibility‑разметкой. В итоге LLM получает неполное представление и не может дать точный ответ.

На помощь приходит VLM — визуальная языковая модель, которая умеет анализировать не только текст, но и изображения. Агент делает скриншот экрана, отправляет его в VLM и получает осмысленный анализ того, что на экране происходит: какие элементы видны, в каком состоянии интерфейс, есть ли что‑то необычное. Мы также можем использовать VLM и для обдумывания действий: даже флагманские модели не могут все делать за один проход, поэтому мы явно сделали разделение на два этапа: reasoning и acting.


Мы используем большую открытую модель с MoE‑архитектурой, показывающую высокие метрики на чисто визуальных бенчмарках.

Итого: у агента есть руки (навигационный движок), глаза(VLM acting) и мозг (VLM reasoning).

Как протестировать приложение с агентом

Как протестировать приложение с агентом

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

  • задание — пошаговый сценарий, описывающий, что нужно сделать;

  • глаза — скриншот текущего экрана и его VLM‑анализ;

  • руки — набор доступных действий (тап, свайп, ввод текста и другие);

  • память — история уже выполненных шагов и их результатов.

На каждом шаге агент смотрит на экран, соотносит увиденное с текущим заданием и выбирает следующее действие из доступного набора инструментов. Если что‑то пошло не так, например ожидаемый экран не появился, агент пытается скорректировать свои действия, опираясь на контекст и историю.

Это принципиально отличается от классических E2E‑тестов, где каждый шаг жестко привязан к конкретному элементу по ID или XPath. Агент оперирует визуальным и смысловым пониманием интерфейса, именно поэтому он устойчивее к изменениям UI.

# Упрощенный раннер. Агент выполняет шаги последовательно, после
# каждого шага верифицирует ожидаемый результат VLM-ом.

def run(self, test_scenario):
    steps = {s["id"]: s for s in test_scenario["steps"]}
    current_step_id = test_scenario["steps"][0]["id"]

    # Подготовка: прекондиции, установка приложения, логин.
    self._apply_preconditions()
    self._prepare_app()
    self._ensure_logged_in()

    # Основной цикл: пока есть следующий шаг.
    while current_step_id:
        step = steps[current_step_id]
        result = self._run_step(step)      # действие + скриншот + VLM-анализ

        # Если ожидаемый результат не сошелся — стоп.
        if not result["verification_passed"]:
            print(f"Step {step['id']} failed verification")
            current_step_id = ""           # сценарий завершен с ошибкой
            break

        # Иначе — переходим к следующему шагу сценария.
        current_step_id = step.get("next_step", "")

    return self._finalize(current_step_id)

Хранилище тест‑кейсов и парсер. Все тест‑кейсы живут в нашем Allure — это единый источник правды и для QA, и для агента. Агент не работает с тестами напрямую: между Allure и агентом стоит парсер, который превращает описание теста в пошаговый сценарий, понятный агенту.

Платформа отчетов. После завершения прогона все результаты попадают в самописную веб‑платформу. Для каждого теста QA видит: пройден он или нет, на каком шаге произошло расхождение, скриншоты экранов с комментариями агента и его «рассуждением» о том, что пошло не так. Это позволяет QA‑инженеру быстро принять решение, не проходя тест вручную: подтвердить дефект или отметить ложное срабатывание.

Тесты для агента

Может показаться, что на этом агент готов: есть движок, есть модель, есть платформа. Самая неожиданная сложность оказалась не в коде, а в самих тестах.

Реальность заставила сильно притормозить. Тестов в нашем Allure очень много — тысячи, тысячи их! Но выяснилось, что подходит лишь малая часть. Основная проблема была в том, что QA‑инженеры пишут тесты для себя: они уже в контексте продукта, знают названия экранов, помнят, где какая кнопка. Описание вроде «перейти в раздел кредитов и проверить историю» понятно человеку в контексте, но абсолютно бесполезно для агента.

Тесты, написанные для людей, не работают для агента. Это ключевая проблема и самый неочевидный инсайт из всего проекта.

Агент — по сути, человек, который впервые в жизни открыл наше приложение. У него нет контекста, нет насмотренности, нет памяти о прошлых прогонах. Если в тесте написано «открой экран операций по счету карты Black», агент не знает, что для этого нужно нажать на вкладку «Главная» → найти блок с картой Black → тапнуть этот блок → перейти в историю операций. QA‑инженер это знает, потому что видел этот экран сотни раз. Агент — нет.

Для человека:

Шаг 1: нажать на виджет Black.
Шаг 2: перейти в историю операций.
Ожидаемый результат: список операций отображается корректно.

Для агента:

Шаг 1: нажать на вкладку «Главная».
Шаг 2: на главном экране найти виджет Black (может потребоваться скролл вниз). Нажать на него.
Шаг 3: на экране счета найти виджет или ссылку «История операций» / «Операции по счету». Нажать.
Ожидаемый результат: на экране виден список операций с датами и суммами. Нет сообщений об ошибках. Список не пуст.

Видим, что появляется более полное описание, неявные шаги, которые QA‑инженер выполняет неосознанно, явные указания ожиданий во время проверок. И это становится проблемой.

Как мы решали проблему адаптации. Решение пришло поэтапно.

Этап 1 — ручная адаптация по инструкции. Мы составили для QA‑инженеров набор правил: как описывать шаги, какой уровень детализации нужен, как формулировать ожидаемые результаты, чтобы они были проверяемы визуально. Это решает проблему, но прибавляет работы самим QA.

Этап 2 — автоматизация парсинга. Мы начали строить умный парсер, который берет тест из Allure и сам превращает его в адаптированный сценарий. Внутри — комбинация rule‑based‑логики для типовых паттернов и VLM‑обработки для нестандартных случаев текстом. Ведь обычно для теста нужно подготовить не только сам сценарий, но и начальные условия — preconditions. Например: авторизоваться под пользователем с кредитом, подключить мок для определенного API, включить нужные фича‑флаги. Парсер умеет извлекать эти условия из описания теста и передавать агенту.

Преобразование теста под агента

Преобразование теста под агента

Текущий вариант не конечный и, вполне вероятно, изменится в будущем. Полностью автоматический парсинг — это цель, к которой мы идем. Сейчас часть тестов все еще требует ручной доводки, но доля автоматически адаптированных сценариев растет.

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

  • Тесты с неявными preconditions. «Проверить пуш‑уведомление после оплаты» — подразумевается, что перед этим нужно совершить оплату, получить уведомление и только потом проверять. В описании теста этих шагов может не быть.

  • Тесты с внешними зависимостями. «Проверить, что пуш приходит после оплаты через СБП» — тест зависит от внешнего сервиса, который может быть недоступен на стенде или работать нестабильно. Агент не может контролировать поведение внешних систем.

  • Тесты с визуальными сравнениями по памяти. «Убедиться, что экран выглядит как раньше» — у агента нет «раньше», ему нужен конкретный эталон.

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

Границы применения. Теперь, когда понятно, как агент работает и с чем сталкивается, поговорим о том, где мы его применяем и какие у него границы. У нас сложилось три основных сценария использования. Они различаются по частоте, глубине проверки и роли QA.

1. Регресс и смоук‑прогоны — основной и самый частый сценарий, тот самый, ради которого все начиналось. Агент проходит набор тест‑кейсов из Allure перед релизом, проверяя ключевые пользовательские сценарии.

Сейчас прогоны можно запустить вечером и получить отчет к утру. QA остается верификация результатов, а это принципиально другой уровень нагрузки: просмотреть отчет с пометками агента значительно быстрее, чем пройти все сценарии вручную.
Смоук‑прогоны работают по тому же принципу, но на сокращенном наборе тестов — их удобно запускать после каждой сборки, чтобы убедиться, что ничего критичного не сломалось.

2. Прогон сценариев по запросу. Не только регресс. Агент полезен в ситуациях, когда нужна быстрая проверка:

  • После глобальных изменений — обновление дизайн‑системы, миграция на новую версию библиотеки, рефакторинг навигации. Нужно убедиться, что не сломалось то, что не трогали.

  • Дабл‑чек — QA прошел тест руками, но хочет перепроверить на другом устройстве или с другими данными. Агент делает это без дополнительных затрат времени человека.

  • Проверка гипотез — продакт хочет понять, работает ли флоу так, как задумано. Достаточно описать сценарий, и агент пройдет его от начала до конца с полным отчетом.

3. Отдельный сценарий — продукты, где полноценная QA‑команда экономически неоправданна. Это внутренние инструменты, продукты на этапе MVP/PoC, эксперименты. Здесь агент может работать как основная линия тестирования: разработчик описывает сценарии, агент их проходит, разработчик смотрит отчет.

Важно оговориться: AI‑агент — не серебряная пуля и не замена всему. Экономически он оправдан в ситуациях:

  • продукты с большим объемом регресса, где ручное прохождение занимает дни;

  • команды без выделенной автоматизации, где тесты существуют только в ручном виде;

  • продукты средней и низкой критичности, а также этапы MVP/PoC, где полноценная автоматизация избыточна;

  • фичи под A/B‑тестами и фича‑флагами, где количество комбинаций для проверки множится, а ресурсы — нет.

Ограничения применения агента

У агента есть четкие границы, и мы считаем важным говорить про них открыто. 

Ложные срабатывания. Агент может сигнализировать о проблеме там, где ее нет. Типичные причины:

  • Динамический контент, зависящий от фича‑флагов и ответа от сервера от стороннего API.

  • Медленная загрузка — экран не успел прогрузиться к моменту скриншота, агент видит промежуточное состояние.

  • Неоднозначные ожидаемые результаты — если в тесте написано «список отображается корректно», у агента и у QA может быть разное понимание «корректно».

Мы работаем над снижением false positive rate, но пока верификация QA‑инженером остается обязательным шагом.

Пропущенные дефекты. Обратная сторона — агент может не заметить проблему. Особенно это касается:

  • Мелких UI‑дефектов — сдвиг элемента на несколько пикселей, неправильный цвет, некорректный шрифт.

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

Ограничения важно не только понимать, но и уметь измерять. Когда мы начали замерять качество работы агента, столкнулись с неожиданной проблемой: привычная градация дефектов (critical / major / minor / trivial) нам не подошла.

Агент отлично справляется с крашами, серьезными визуальными поломками, проблемами с текстами и локализацией. Но при этом он не видит pixel‑perfect‑дефекты — элемент сдвинут на 6 пикселей относительно макета, отступ 10px вместо 16px. Для агента это не проблема — визуально все читаемо и функционально. А вот QA‑инженер, который видит этот экран в сотый раз, замечает такие сдвиги достаточно быстро. Значит, нам нужна категоризация, которая отражает не критичность дефекта для пользователя, а способность агента его обнаружить. Так появился светофор.

🔴 Красные дефекты — то, что агент видит хорошо:
 — краши и нерабочие экраны;
 — серьезные визуальные поломки (элементы наезжают друг на друга, контент не отображается);
 — ошибки в текстах и локализации;
 — нерабочие интерактивные элементы (кнопка не нажимается, переход не работает).

Это дефекты, которые заметит любой человек, даже без знания продукта — и агент тоже.

🟡 Желтые дефекты — пограничная зона:
 — мелкие UI‑баги, не блокирующие работу: кнопка не того размера, элемент заходит на статус‑бар, некорректный цвет;
 — пользоваться приложением можно, но визуально что‑то не так.

🟢 Зеленые дефекты — pixel‑perfect:
 — отступ 10px вместо 16px;
 — шрифт 14pt вместо 15pt;
 — цвет #333 вместо #222.

Зеленые дефекты это то, что находят только QA при ручном сравнении с макетом. Агент на текущем этапе с этим не справляется, и мы сознательно не ставим это целью прямо сейчас. Граница между желтым и зеленым бывает размытой. Например, если элемент наехал на статус‑бар и наполовину закрывает системное время — это желтый дефект. Если заехал на пару пикселей — уже зеленый.

И над зеленым дефектами мы вполне можем начать работать: можно отдавать агенту макеты и заставлять его сравнивать текущий экран с эталоном. Однако это уже немного другой уровень сложности, к которому мы придем в будущем.

Как собирали данные для бенчмарка и какие результаты получили

На этапе проработки гипотезы я собрал первый бенчмарк самостоятельно. Основной источник — заведенные дефекты в Jira: я брал реальные баги, экраны с ними и экраны без дефектов и размечал каждый по нашей категоризации. Дальше мы привлекли QA‑инженеров: они проходили опрос, где отмечали экраны с дефектами и без, добавляли описания. Это позволило расширить датасет и снизить субъективность моей разметки.

В итоге получился первый бенчмарк — 150+ размеченных примеров: экраны с дефектами разных категорий и экраны без дефектов. Мы провели ревью этого бенчмарка вместе с QA — скорректировали часть разметки, но сама категоризация «светофор» подтвердилась: все согласились, что деление жизнеспособное и отражает реальную картину.

Методика простая. Для каждого примера из бенчмарка известно, есть ли на экране дефект. Мы прогоняем агента и смотрим, что он ответит. Дальше сопоставляем:

Дефекта нет

✅ Корректно

❌ Ложное срабатывание

Дефект есть

❌ Пропуск

✅ Найден

Итоговая метрика — accuracy: доля правильных ответов (и корректных «ОК», и найденных дефектов) от общего числа примеров. Accuracy как единственная метрика имеет ограничения: она не учитывает, что пропуск дефекта и ложное срабатывание имеют разную «цену». Мы это понимаем и в дальнейшем планируем считать precision и recall отдельно. Но для первого бенчмарка и валидации гипотезы accuracy дает достаточную картину.


На красных дефектах мы получили 87% — в 87 случаях из 100 агент дает правильный ответ: находит дефект, когда он есть, и не сигнализирует, когда его нет. На экранах без дефектов агент в подавляющем большинстве случаев корректно отвечает «все ОК» и не заваливает QA ложными срабатываниями. Иначе инструмент просто не имел бы смысла: если бы каждый второй «найденный баг» оказывался бы фантомным, QA тратил бы на перепроверку больше времени, чем на ручной регресс.

Для первого бенчмарка это сильный результат: он подтвердил, что подход рабочий.
На желтых дефектах — 61%. На зеленых — 56%, что ненамного лучше случайного угадывания. Это ожидаемо: зеленые дефекты — по определению то, что видно только при сравнении с макетом, а агент на текущем этапе этого не делает.

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

Еще одна важная метрика — время прохождения одного теста агентом. Сейчас средний для нас тест, состоящий из 8 шагов, проходится за 3 минуты. Это с учетом конфигурирования и поднятия симуляторов, выставления тестовых юзеров — в общем, со всей подготовкой. Это достаточно много, но нас это устраивает. Но есть положительный инсайт: для сценариев критического пути, которые состоят из очень большого количества шагов и где нужно много моков на запросы во время теста, агент работает быстрее, чем человек. Если продолжать улучшать работу окружения и заниматься оптимизацией — время можно сократить. 

Эвалы. Замер качества определения дефектов агентом — всего лишь одна из стадий работы агента. Для любой AI‑based — системы нужно выстраивать полноценную систему эвалов — системы замера качества на каждом из возможных этапов. 

Помимо этапа верификации один из ключевых этапов — попадание в UI‑элементы. По сути мы должны измерить качество трактования моделью задания + изображения и перевод этого в целевое действие — в AI такая задача называется Grounding. Чтобы замерить такую задачу, необходимо иметь подходящий датасет, как и во всех задачах, связанных с AI. В общем доступе есть достаточно много датасетов, которые измеряют качество такой задачи в GUI Agent (Graphical User Interface), например ScreenSpot, Android in the Wild, ScreenQA и другие. 

Все датасеты в разных форматах и зачастую не содержат полезного сигнала — как модель справляется с этой задачей на наших интерфейсах. Поэтому мы собрали свой датасет на базе нашего приложения. Для этого написали автоматический экстрактор дерева разметки из приложения с последующим дополнением вручную. Там получилось 9 типов разных элементов, по которым отдельно замеряется попадание внутрь bounding box. Если считать общую цифру — у нас 92% aссuracy на 1100+ различных кейсов. Точно так же нужно делать замер еще нескольких стадий: траекторный замер — как агент следует нужной траектории во время исполнения сценария и правильная интерпретация контекста, передаваемого внутрь.

Цифры — это важно, но за ними стоят изменения в процессах. Агент влияет на работу команд и на роль QA.

Главное изменение — регресс перестает быть блокером. Раньше это был период, когда QA‑команда уходила в режим тишины: все заняты, вопросы подождут, помощь с другими задачами — после регресса. Сейчас значительную часть рутинных проверок берет на себя агент. Мы видим экономию ресурсов команды на ~ 25% в месяц. Под этой цифрой мы учитываем время не только QA, но и dev.

Это не значит, что регресс исчезает. Это также не значит, что агент = замена классических автотестов. Он меняет формат: вместо «QA проходит 100 тестов руками» становится «агент проходит 100 тестов ночью, QA утром верифицирует отчет и проходит руками только то, что требует человеческого внимания». Разница в трудозатратах человека существенная.

Мы видим потенциал для сокращения релизного цикла. Стоит помнить: как и любой AI‑продукт, агентную систему стоит внедрять с большой осторожностью — цена ошибки в тестировании банковского приложения высока.

Тем не менее направление понятно. Агент позволяет:

  • запускать проверки в любое время, не дожидаясь свободного QA — ночью, в выходные, параллельно с другой работой;

  • проверять функциональность на этапе разработки, а не только перед релизом — написал фичу, описал сценарий, запустил агента;

  • делать повторные прогоны без дополнительных затрат — исправил баг, перезапустил тест, получил результат.

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


Агент не заменяет QA‑инженера.
Он забирает на себя рутинную часть работы: прохождение знакомых сценариев, проверку типовых экранов, повторные прогоны после исправлений. То, что занимает часы и не требует квалификации.

Агент высвобождает время для того, что сам делать не умеет и еще долго не научится:

  • исследовательское тестирование — когда QA ищет проблемы не по сценарию, а по интуиции и опыту;

  • тест‑дизайн — проектирование тестов, которые покрывают крайние случаи и нетривиальные сценарии;

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

  • работа с командой — консультации разработчиков, участие в проработке фич, ревью требований.

Агент становится инструментом в арсенале QA — как автотесты, линтеры или мониторинг.

Заменит ли ИИ QA? Да, но ручное тестирование и рутинная проверка сценариев будут все больше автоматизироваться с помощью AI‑агентов и автотестов. Но это не уменьшает ценность QA — наоборот, смещает фокус на более высокий уровень.

Роль QA будет все больше про:

  • метрики качества продукта и процессов;

  • анализ причин дефектов и поиск системных проблем;

  • работу с рисками и приоритизацию зон проверки;

  • качество пользовательского опыта и бизнес‑сценариев;

  • аналитику инцидентов и обратной связи пользователей;

  • выстраивание quality strategy для команды и продукта.

QA будущего — это не человек, который «кликает кнопки руками», а специалист, который отвечает за качество продукта в целом: от требований и архитектуры до продуктовых метрик и пользовательского опыта. То есть профессия не исчезает, а становится ближе к Product Quality.

Что дальше

Мы продолжаем развивать агента в нескольких направлениях:

  • Масштабирование. Цель — распространить на все команды мобильного приложения банка, где это экономически оправданно.

  • Качество на желтых и красных дефектах. 87% на красных — хороший старт, но мы хотим 95%+. Параллельно начинаем работать над желтыми дефектами — мелкими UI‑багами, которые пока ускользают.

  • Другие виды тестирования. Регресс — первый и самый очевидный сценарий. Но мы исследуем применимость агента для monkey‑тестирования — свободного «прокликивания» приложения без заданного сценария с целью найти краши и аномалии.

  • Проверка продуктовых гипотез. Возможность быстро прогнать пользовательский флоу без привлечения QA может быть полезна продакт‑менеджерам на ранних этапах проработки фичей.

Работа с таким агентом — это не только про автоматизацию существующих тестов, но в большей степени про изменение процессов в будущем.

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

Агент уже сейчас способен забрать на себя значительную часть рутинных проверок и дать QA‑инженерам то, чего им хронически не хватает — время. Следите за нашими обновлениями, скоро вернемся с новостями и новыми инсайтами. 

View the original on Хабр

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.