Генерація unit- та e2e-тестів з ШІ: як обрати інструменти
Коротка відповідь: для unit-тестів найкорисніші помічники, які працюють безпосередньо з кодом і вашим наявним засобом запуску тестів, тобто бачать функцію, її залежності й поточні тести. Для e2e-тестів, які проходять сценарій користувача від початку до кінця, потрібні інструменти з доступом до браузера і до станів застосунку, які можна перевірити. Універсально найкращого продукту немає: без однакового порівняльного тесту на вашому коді будь-який рейтинг — це думка, а не вимірювання.
Головна умова вибору — тести мають знаходити реальні дефекти. Кількість згенерованих файлів, приріст покриття і зелений запуск самі по собі цього не доводять: тест може успішно проходити, повторюючи ту саму помилку, що й код. Після прочитання ви зможете скласти протокол порівняння інструментів, визначити критерії прийняття згенерованих тестів і правила для автоматичного «лікування» тестів, яке не приховує баги.
Unit і e2e розв’язують різні задачі
Unit-тест перевіряє окрему функцію чи клас: на такі входи — такий результат. У найпростішому випадку він запускається швидко й не потребує браузера; зовнішні залежності за потреби замінюють заглушками. Якщо тест використовує реальну базу чи мережу, це вже інший за витратами сценарій, який слід оцінювати окремо. Його цінність — швидко показати, що конкретна логіка зламалася, і вказати, де саме.
E2e-тест перевіряє шлях користувача: відкрити сторінку, увійти, додати товар у кошик, оформити замовлення, побачити підтвердження. Він потребує розгорнутого застосунку, тестових даних, облікових записів і браузера. Він повільніший і крихкіший, зате перевіряє те, що бачить клієнт, включно з інтеграцією між частинами системи.
Звідси різні вимоги до ШІ-інструментів. Для unit-тестів потрібен доступ до коду, типів, наявних тестів і можливість запускати їх. Для e2e — доступ до працюючого застосунку, вміння знаходити елементи сторінки й перевіряти стан не лише на екрані, а й у системі: чи справді замовлення збереглося з правильною сумою.
Які класи інструментів порівнювати
Замість рейтингу продуктів корисніше розуміти класи інструментів і критерії, за якими їх порівнювати.
Помічник у середовищі розробки. Пропонує тести для відкритого файлу чи виділеної функції. Зручний для швидких заготовок, але бачить обмежений контекст.
Агент у репозиторії. Може читати кілька файлів, запускати тести, аналізувати результат і повторювати спробу. Підходить для серії тестів до модуля, але потребує обмеження прав і уважного рев’ю змін.
Браузерний агент. Працює з реальним інтерфейсом: досліджує сторінки, пише сценарії, оновлює їх. У Playwright передбачено три ролі агентів: планувальник досліджує застосунок і складає план тестування у форматі Markdown, генератор перетворює план на виконувані тести, перевіряючи локатори й перевірки під час проходження сценарію, а «лікар» (healer) запускає тест, що падає, і пропонує виправлення локатора, очікування стану або тестових даних. Зміни очікуваного бізнес-результату вимагають окремої перевірки людиною.
Керований сервіс. Зовнішня платформа, яка сама зберігає і запускає тести. Знімає частину інфраструктурних задач, але додає залежність від постачальника і питання доступу до тестового середовища.
Критерії порівняння однакові для всіх класів: на якому контексті працює інструмент; де виконуються тести; хто визначає очікуваний результат; скільки коштує супровід згенерованих тестів; чи падають тести на внесених вами дефектах.
Навчальна таблиця порівняння
| Тип тесту | Доступний контекст | Де виконується | Хто задає очікуваний результат | Вартість супроводу |
|---|---|---|---|---|
| Unit, помічник у редакторі | Відкритий файл, частина залежностей | Локально, наявний засіб запуску | Розробник; ризик, що модель візьме очікування з самого коду | Низька, якщо тест не прив’язаний до деталей реалізації |
| Unit, агент у репозиторії | Модуль, наявні тести, результати запусків | Локально або в CI | Розробник за контрактом; агент лише пропонує | Середня: багато нових файлів, треба рев’ю |
| E2e, браузерний агент | Інтерфейс, тестові дані, план сценарію | Тестове середовище з браузером | QA за бізнес-сценарієм | Вища: залежить від стабільності інтерфейсу і даних |
| E2e, керований сервіс | Інтерфейс і налаштування платформи | Інфраструктура постачальника | QA; потрібен контроль змін у перевірках | Залежить від умов сервісу і доступу до середовища |
Таблицю варто заповнювати для свого стеку, а не брати як оцінку конкретних продуктів.
Як підготувати контекст
ШІ не знає, як має працювати ваш бізнес. Якщо дати йому лише код, він виведе очікування з коду, тобто перевірить, що код робить те, що робить. Тому до генерації потрібно підготувати:
- Бізнес-контракт. Що функція чи сценарій мають гарантувати: «знижка не більше 30%», «замовлення з нульовою сумою не створюється», «після оплати статус — "оплачено"».
- Фікстури. Підготовлені тестові дані: товари, клієнти, тарифи. Стабільні, відомі, без реальних персональних даних.
- Допустимі побічні ефекти. Що тест може змінювати: записи в тестовій базі — так, відправку листів реальним клієнтам — ні.
- Тестові облікові записи з різними ролями: адміністратор, менеджер, звичайний клієнт.
- Наявні домовленості. Структура тестів, назви, допоміжні функції, підхід до заглушок. Згенеровані тести мають виглядати як написані командою.
У Playwright, наприклад, планувальнику можна передати не лише запит, а й початковий тест, який налаштовує середовище, і за бажанням документ із вимогами до продукту. Що точніший такий вхід, то менше доведеться виправляти після генерації.
Як приймати unit-тести
Згенерований unit-тест варто приймати за тими самими правилами, що й написаний людиною, плюс кілька спеціальних перевірок.
Межі. Чи перевірено граничні значення: нуль, від’ємні числа, порожній список, максимальна довжина, некоректний формат.
Незалежність очікуваного результату. Очікуване значення має братися з контракту чи ручного розрахунку, а не з виклику тієї самої функції. Тест виду «результат функції дорівнює результату функції» нічого не перевіряє.
Навчальний приклад, як ця різниця виглядає на практиці. Контракт функції знижки: «для замовлень від 10 000 гривень знижка 5%, але не більше 1 000 гривень». У коді є помилка: обмеження 1 000 гривень не застосовується. Модель, яка бачить лише код, напише тест «замовлення на 30 000 гривень → знижка 1 500 гривень», бо саме так код рахує зараз. Тест пройде і закріпить помилку. Тест, побудований з контракту, очікуватиме 1 000 гривень і впаде — тобто виявить дефект ще до того, як його побачить клієнт. Тому для генерації варто давати моделі контракт окремо від коду і прямо вимагати, щоб очікувані значення бралися з контракту. А під час рев’ю перевіряти не лише «чи тест проходить», а й «звідки взялося очікуване число». Якщо відповідь «з результату функції», тест треба переписати.
Ще одна корисна вимога до запиту: попросити модель окремо перелічити граничні випадки, які вона вважає важливими, ще до написання тестів. Такий список легко перевірити очима — чи є там рівно 10 000 гривень, сума трохи нижче порогу, сума, де 5% якраз дорівнюють обмеженню, від’ємне чи нульове значення. Пропущений випадок видно одразу, а не після аналізу сотні рядків тестового коду.
Не перевіряти власні заглушки. Якщо тест замінює залежність заглушкою, а потім перевіряє лише те, що заглушку викликали з потрібними параметрами, він тестує сам себе. Такий тест пройде, навіть якщо реальна логіка зламана.
Здатність зловити дефект. Найпрактичніша перевірка: навмисно внести помилку в код — поміняти знак порівняння, прибрати перевірку, змінити константу — і переконатися, що тест упав. На цій ідеї побудоване мутаційне тестування: спеціальні інструменти автоматично вносять такі зміни і рахують, скільки з них тести виявили.
Показовий приклад автоматичної фільтрації — внутрішня система генерації тестів, описана у 2024 році. Вона пропускала запропоновані моделлю тести через послідовні фільтри: чи тест збирається, чи стабільно проходить, чи додає покриття. В оцінці на двох конкретних продуктах 75% згенерованих тестів зібралися, 57% стабільно пройшли, а 25% збільшили покриття. Під час внутрішніх тестових сесій система покращила тести для 11,5% класів, до яких її застосували, а інженери прийняли 73% її рекомендацій у робочий код. Це внутрішній інструмент на конкретній кодовій базі, і цифри не обіцяють такого самого результату для вашого репозиторію. Головний урок інший: не варто приймати всі генерації, кожну треба автоматично відфільтрувати, а людина переглядає вже відфільтроване.
Як приймати e2e-тести
Для e2e-тестів додаються проблеми стабільності.
Стійкі локатори. Елементи шукаються за роллю, підписом чи спеціальним тестовим атрибутом, а не за довгим шляхом у структурі сторінки, який ламається від будь-якої зміни верстки.
Керовані дані. Тест створює потрібні йому дані або використовує заздалегідь підготовлені і не залежить від того, що лишилося після інших тестів.
Очікування стану замість пауз. Тест чекає, доки з’явиться конкретний елемент чи зміниться статус, а не «спить» фіксовані п’ять секунд. Фіксовані паузи роблять тести одночасно повільними і нестабільними.
Незалежність від порядку. Кожен тест має проходити окремо і в будь-якій послідовності з іншими.
Перевірка стану системи, а не лише екрана. Напис «Дякуємо за замовлення» не доводить, що замовлення збереглося з правильною сумою.
Навчальний сценарій e2e: оформлення замовлення
Сценарій: клієнт додає в кошик два товари, застосовує промокод, оформлює замовлення. Тест перевіряє, що на екрані підтвердження сума правильна, і окремо — через тестовий API або базу — що замовлення збережене зі статусом «очікує оплати» і тією самою сумою.
Тепер дві ситуації після оновлення застосунку. Перша: кнопку «Оформити» перейменували на «Підтвердити замовлення». Тест падає, бо не знаходить кнопку. Оновити локатор — нормальне виправлення: змінився інтерфейс, а не поведінка. Друга: після оновлення сума в замовленні на 50 гривень більша, бо промокод перестав застосовуватися. Тест падає на перевірці суми. Змінити очікувану суму, щоб тест знову пройшов, не можна: тест зробив саме те, для чого існує, — знайшов дефект.
І окремо про покриття: навіть якщо після генерації покриття рядків зросло, це не доводить відсутності дефектів. Покриття показує, які рядки виконалися, а не те, чи правильні перевірки.
Як оцінювати автоматичне виправлення
Найчутливіше місце в генерації тестів — автоматичне «лікування». Інструмент бачить тест, що падає, і змінює його так, щоб той пройшов. Іноді це правильно, іноді — приховування бага.
У Playwright агент-«лікар» відтворює кроки тесту, що впав, шукає в інтерфейсі відповідні елементи чи сценарії і пропонує виправлення: оновити локатор, скоригувати очікування стану або виправити дані. Він повторює запуск, доки тест не пройде або доки не спрацюють обмеження. Якщо агент вважає, що зламана сама функціональність, він може позначити тест як пропущений. Це розумна поведінка, але пропущений тест — це теж сигнал, який хтось має прочитати: інакше дефект просто зникне з поля зору.
Тому потрібні чіткі правила:
- Дозволено без додаткового погодження: оновлення локатора, якщо змінився лише інтерфейс; заміна фіксованої паузи на очікування стану; виправлення тестових даних, які застаріли.
- Потребує пояснення і погодження: будь-яка зміна очікуваного результату — суми, статусу, кількості, тексту повідомлення. Автор зміни пояснює, чому змінилася вимога, і посилається на рішення, яке її змінило.
- Заборонено: тихо змінювати перевірку під поточний результат; масово позначати тести пропущеними без розбору; видаляти тест, що падає, без задачі на з’ясування причини.
Запропоновані ШІ-виправлення потребують перегляду людиною; наявні тести допомагають перевірити, чи не змінилася поведінка після виправлення. Для тестів логіка та сама: зміна тесту — це зміна контракту, і вона проходить рев’ю.
Підсумок і перші кроки
ШІ може суттєво пришвидшити створення заготовок тестів, пошук граничних випадків і підтримку e2e-сценаріїв. Але цінність тесту визначається тим, чи знаходить він дефекти, а не тим, хто його написав і чи він зелений.
Що можна зробити на своєму проєкті:
- Для одного модуля записати бізнес-контракт: що функції гарантують і що заборонено.
- Обрати два-три інструменти з різних класів і дати їм однакову задачу на одному й тому самому коді.
- Для кожного набору згенерованих тестів внести кілька навмисних дефектів і порахувати, скільки з них тести виявили.
- Для e2e обрати один критичний сценарій, наприклад оформлення замовлення, і додати перевірку стану в системі, а не лише на екрані.
- Записати правила автоматичного виправлення: що дозволено, що потребує погодження, що заборонено.
- Налаштувати сповіщення про тести, позначені пропущеними, і розбирати кожен такий випадок.
Порівняння інструментів для тестування найпростіше почати з одного модуля й одного критичного сценарію. Якщо потрібно вирішити, які саме взяти, які критерії прийняття закріпити і хто супроводжуватиме згенеровані тести у вашому CI, з цим можна прийти на консультацію до BotLabs: розберемо ваш процес тестування і визначимо межі пілоту.
Часті запитання
Ні. Покриття рядків показує, які рядки виконалися під час тестів, але не те, чи правильно перевірено результат. Тест може виконати кожен рядок функції і не мати жодної змістовної перевірки, або перевіряти лише власні заглушки. Набагато показовіше, чи падають тести на навмисно внесених дефектах і чи перевіряють вони бізнес-контракт, а не поточну поведінку коду.
Лише за умови, що зміст кожної зміни перевіряє людина. Оновити локатор після перейменування кнопки — нормально. Змінити очікувану суму чи статус, щоб тест пройшов на поточному коді, — неприпустимо без пояснення і рішення про зміну вимоги. Окремо варто стежити за тестами, які інструмент позначив пропущеними: вони можуть вказувати на реально зламану функціональність.
Внесіть у код дефект, який цей тест має виявляти, — наприклад, змініть умову чи приберіть перевірку — і переконайтеся, що тест упав. Потім поверніть правильний код і переконайтеся, що тест проходить. Додатково перевірте, що очікуване значення взяте з контракту, а не з виклику тієї самої функції, і що тест не залежить від зайвих деталей реалізації, які можуть змінитися без зміни поведінки.
Консультація з прийняття ШІ-тестів
За 15 хвилин із технічним фахівцем BotLabs обговоримо один модуль або e2e-сценарій і критерії прийняття згенерованих тестів. Визначимо, звідки брати очікуваний результат і який дефект використати для перевірки тестів; наступний крок — обмежений пілот у вашому процесі QA.
Згенеровані тести
Критерії прийняття
15 хвилин із фахівцем: обговоримо критерії прийняття тестів і перевірку на відомому дефекті.


