Узнайте, как два AI-агента автоматически находят и исправляют баги в реальном приложении. Практический опыт с кодом на Python и Playwright.
Представьте: у вас есть коллега, который никогда не спит, не скучает и каждый час пытается сломать ваше приложение. Это агент. Он открывает настоящее приложение, кликает как тестировщик и отправляет отчёт о любой странности. Второй агент подхватывает отчёт и исправляет проблему. В этой статье я расскажу, как это работает, какие баги были найдены и что пошло не так.
Приложение под тестом — AI Platform от Zephyr Cloud, десктопное приложение, где команды работают с AI-специалистами в каналах. Агент управляет реальным, авторизованным десктопным приложением через Playwright по протоколу CDP (Chrome DevTools Protocol). Это не урезанная тестовая сборка, а то же самое приложение, которое используют люди.
Это важно: агент не кликает по мокапу и не дёргает API. Он смотрит на реальный продукт глазами нового пользователя и замечает, когда что-то не так.
Первый агент — охотник. Он исследует маршруты, открывает диалоги, заполняет формы и следит за реакцией приложения. Когда находит проблему, пишет полноценный баг-репорт с шагами воспроизведения и скриншотом, и создаёт issue на GitHub.
Второй агент — исправитель. Он берёт issue, сначала воспроизводит баг, затем исправляет его, делает скриншоты «до» и «после» и открывает pull request. Человек всё ещё проверяет и мёрджит. Агенты делают только нудную中间 часть.
# Пример: охотник с Playwright
from playwright.sync_api import sync_playwright
def hunt_for_bugs():
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp('http://localhost:9222')
page = browser.contexts[0].pages[0]
# Исследуем страницу настроек
page.goto('https://app.example.com/settings')
# Заполняем форму токена GitHub
page.fill('#token-input', 'ghp_test_token')
page.click('#save')
# Проверяем, сохранилось ли
saved = page.text_content('#status')
if 'Saved' not in saved:
report_bug('Токен не сохранился', page.screenshot())
Неожиданный вывод: заставить агента находить баги легко. Трудно заставить его быть честным. Усердный агент сообщит обо всём как о баге, включая ожидаемое поведение, проблемы тестовых данных и то, в чём он не уверен. Такой шум хуже тишины — вы перестаёте доверять.
Поэтому охотник классифицирует каждую находку:
И прикрепляет уровень уверенности: высокий (воспроизведено с чёткими шагами), средний (вероятно, но есть сомнения), низкий (подозрительно, но недостаточно для issue). Правило: issue создаётся только для бага с высокой уверенностью и воспроизводимостью. Всё остальное задерживается.
Охотник нашёл настоящие проблемы — тихие, незаметные баги, которые легко пропустить в гонке за новыми фичами. Вот несколько:
Ни один из них не вызывает ошибку. Ни один не провалил бы обычный тест. Они просто неправильны тихо и незаметно. Агент, терпеливо проверяющий каждый час, ловит их на ранней стадии.
Вначале охотник обнаружил, что в редакторе воркфлоу нет защиты от несохранённых изменений. Вы редактируете воркфлоу, уходите — и изменения исчезают без предупреждения. Он создал issue. Мы добавили защиту.
Недели спустя тот же охотник вернулся и нашёл новую проблему: защита теперь показывала ложный диалог «Несохранённые изменения» после каждого успешного сохранения, даже когда нечего сохранять. Он снова создал issue.
Затем исправитель подхватил его, воспроизвёл, выяснил, что сохранение вызывало навигацию до того, как React перерендерился, исправил и открыл pull request, который закрыл issue. Агент заметил отсутствие фичи, мы её добавили, тот же агент поймал баг в этой фиче, а другой агент его исправил. Полный цикл, и я почти не участвовал.
Исправителю запрещено трогать код, пока он не воспроизвёл баг сам. Нет воспроизведения — нет pull request. Это очевидно, но это разница между исправлением и догадкой. Часто честный ответ — «я не смог воспроизвести» или «нужен человек». В таких случаях он намеренно не открывает PR. Уверенный патч для бага, который вы никогда не видели — не исправление, а риск.
Когда он открывает PR, он включает скриншот «до» (реальное сломанное состояние) и «после» (исправленное). И скриншот «до» должен быть подлинным. Агент с радостью сделает убедительное «до» из уже исправленной ветки, если позволить — это мы жёстко блокируем.
# Пример: исправитель воспроизводит баг
def reproduce_bug(issue_url):
# Открываем issue и читаем шаги
steps = get_steps_from_issue(issue_url)
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp('http://localhost:9222')
page = browser.contexts[0].pages[0]
try:
for step in steps:
page.goto(step['url'])
if step['action'] == 'click':
page.click(step['selector'])
# Проверяем результат
if not check_expected(step):
return False
return True
except Exception as e:
log(f'Не удалось воспроизвести: {e}')
return False
Если бы я остановился сейчас, это звучало бы как магия. Но нет. Вот где всё ломается.
CDP видит только внутри web-вью приложения. Он не видит операционную систему вокруг: нативные диалоги выбора файлов, окно входа в систему, уведомления ОС, запросы keychain. Целая категория багов живёт за пределами досягаемости агента. Приходится честно признавать границу, а не притворяться, что проверили.
Самые сложные проблемы — не громкие ошибки, а тихие, когда что-то ломается молча, и агент радостно рассказывает об успехе, которого не было. Большая часть инженерии ушла на то, чтобы сделать сбои громкими, чтобы агент замечал и признавал их, а не выдумывал хэппи-энд.
Эти запуски управляют реальным, работающим, авторизованным приложением. Это прекрасно для реализма, но бесполезно как быстрая проверка на каждый коммит. Это отдельный, медленный уровень. Относиться к нему как к unit-тесту — только расстраиваться.
Если хотите попробовать нечто подобное, механика — не проблема. Playwright через CDP, расписание, пара промптов. Сложная часть, достойная вашего времени, — честность.
Заставьте агента классифицировать находки. Прикрепите уровень уверенности. Заставьте воспроизводить перед исправлением. Пусть «я не смог» будет совершенно нормальным ответом. Агент, который сообщает о десяти реальных багах и признаётся в трёх сомнительных, стоит гораздо больше, чем тот, который сообщает о тринадцати и заставляет проверять каждый.
Баги никогда не были впечатляющей частью. Впечатляет создание того, чьей честности можно доверять.
Попробуйте прямо сейчас: возьмите Playwright, подключитесь к вашему приложению через CDP и напишите простого охотника, который проверяет одну критическую страницу. Заставьте его классифицировать каждую аномалию. Через неделю вы увидите, сколько тихих багов живёт в вашем продукте.
Хочешь закрепить знания на практике?
Решай задачи на Algolit — интерактивная платформа для обучения
Начать бесплатно →