Підтримка тестів і аналіз падінь
Зміст
Автотести пишуть один раз, а супроводжують роками. Реальний час AQA витікає не на написання нового тесту, а на розбір червоного прогону вранці: що впало, чому впало, це баг продукту чи наш тест просто відстав від інтерфейсу. Саме тут AI спокушає найсильніше — кинути йому лог і спитати «що не так» здається способом зекономити годину . Іноді так і є. А іноді модель упевнено назве неправильну причину, ви полагодите не те, і червоне повернеться завтра.
Ця глава — про те, де AI справді прискорює супровід тестів, а де його діагноз шкідливий. Рамка та сама, що й у всій роботі з AI: модель не бачила вашого прогону, вона працює лише з тим контекстом, який ви їй дали, і видає найправдоподібніший текст, а не істину (механіку розібрано в главі Як працюють LLM). Тому цінність AI у тріажі рівно така, як якість артефактів, що ви йому згодували, і суворість перевірки того, що він відповів. На співбесіді middle-рівня це питають прямо: «як ви користуєтесь AI, коли розбираєте падіння?» — і слабку відповідь («кидаю лог, він каже причину») видно одразу.
Тріаж фейлу: артефакти як контекст для AI
Тріаж (triage) — це первинне сортування червоних тестів: швидко зрозуміти, що впало і куди копати. Головний принцип роботи з AI тут: діагноз рівно настільки хороший, наскільки повний контекст. Модель не має доступу до вашого CI, не бачить екрана, не знає стану бекенду. Усе, що вона «знає» про падіння, — це те, що ви вставили в . Кинути голе Timeout 30000ms exceeded — те саме, що попросити лікаря поставити діагноз за одним словом «болить».
Що реально несе інформацію про падіння:
| Артефакт | Що з нього видно |
|---|---|
| Повідомлення помилки + стек-трейс | Який рядок і який виклик впав, тип помилки |
| Локатор, що не зматчився | Чого саме тест не знайшов на сторінці |
| Скріншот на момент падіння | Що реально було на екрані: не той стан, помилка, порожнеча |
| Trace / відео прогону | Послідовність дій, мережа, консоль, DOM-снапшоти по кроках |
| Мережеві запити (HAR) | Чи прийшов бекенд-виклик, який статус, що в тілі |
| Логи застосунку | Помилки сервера, correlation id, виняток на бекенді |
У Playwright майже все це збирається автоматично у trace-архів (опція trace: 'on-first-retry' записує лише для повторного прогону впалого тесту). Trace viewer дає снапшот DOM на кожному кроці, мережу й — це найбагатший контекст, який можна віддати AI для розбору (детальніше про сам trace viewer — у розділі про інструменти автоматизації). Ключове: згодовуйте AI факти прогону, а не свій переказ. Ваш переказ уже містить вашу гіпотезу, і модель радо до неї «прив'язується».
Фейл ≠ баг: де AI помиляється в діагнозі
Найважливіша ідея всього супроводу: падіння тесту не дорівнює баг застосунку. Червоний прогон має рівно три причини, і плутати їх дорого:
- Баг продукту — застосунок справді працює неправильно. Це те, заради чого тест існує.
- Баг тесту — крихкий , забутий
await, гонка в самому тесті, застарілий крок після зміни UI. Продукт здоровий. - Інфраструктура / — оточення моргнуло, впав сусідній сервіс, тест-дані зайняв інший .
Ця класифікація — канон (розділ «Автоматизація: стратегія», глава про ) і наскрізна тема співбесід; браузерну механіку того, чому UI-тест бачить «не той» стан, розібрано в главі Практичні сценарії AQA: флак і синхронізація.
Тепер про те, як саме AI тут помиляється. Модель дає найправдоподібніший діагноз, а не найправильніший, і в неї є впізнавані патерни хиб:
- Прив'язка до симптому. Це упередження прив'язки (anchoring): бачить
Timeout— радить збільшити . Але таймаут спливає і коли елемента немає через реальний баг, і коли тест чекає не на те. «Збільш таймаут» замасковує гонку замість полагодити її. - Звинувачення застосунку за замовчуванням. AI охоче пише «схоже, у застосунку баг», бо це правдоподібна фраза — навіть коли винен . Для QA це найдорожча помилка: завести баг на здоровий продукт означає спалити довіру команди.
- Вигаданий root cause, що пасує до симптому. Модель сконструює зв'язну причинну історію, яка ідеально пояснює лог і при цьому не має нічого спільного з реальністю. Гладкість тексту не корелює з правильністю — це та сама пастка, що й у главі Верифікація результатів AI.
Практичне правило: AI генерує гіпотези, підтверджуєте їх ви — повторним прогоном, ручним відтворенням кроку, зазиранням у мережу чи БД. Гіпотеза «це баг бекенду» коштує один запит curl для перевірки; не перевіряти її й одразу заводити дефект — антипатерн.
Флакі: аналіз патернів
Ось де AI приносить найбільше чесної користі. Один флакі-фейл людина розбере й сама. А от патерн у сотні прогонів око не бачить — і саме тут модель сильна: згодуйте їй історію падінь (які тести, коли, на яких воркерах, у якому оточенні), і попросіть згрупувати за спільними ознаками.
Типові патерни, які так виринають:
- тест червоніє лише вночі → майже завжди таймзона чи межа доби в даних;
- падає лише на воркері N при паралельному запуску → спільні тест-дані, конфлікт за одним акаунтом;
- зелений локально, червоний лише в CI → headless-таймінги, повільніше оточення, інший стан кешу (див. Кешування);
- серія тестів валиться після одного конкретного → протікання стану, порушена ізоляція.
Чому це працює: LLM добре підсумовує й кластеризує накидані дані. Але межу треба тримати чітко: AI групує симптоми, а не встановлює причину. «Ці п'ять тестів падають на воркері 3» — це кластер, а не діагноз; чому саме воркер 3, з'ясовуєте ви. Модель дає напрямок пошуку й економить години читання логів — не готовий вирок.
Рефакторинг тестів з AI
Супровід — це ще й переписування старого коду, і тут AI сильний, бо більшість рефакторингу — механічні трансформації, які легко перевірити прогоном і diff-ом. Витягнути повторюваний блок у , прибрати дублювання, перейменувати, замінити застарілий патерн на сучасний — усе це модель робить швидко й здебільшого коректно.
Класичний приклад — масова заміна хардкодних очікувань на web-first :
// Було: хардвейт — антипатерн, тримає флак і гальмує прогін
await page.waitForTimeout(3000);
expect(await page.locator('.status').textContent()).toBe('Готово');
// Стало: web-first асерт з авторетраєм, чекає рівно скільки треба
await expect(page.locator('.status')).toHaveText('Готово');
Чому такий рефакторинг відносно безпечний для AI: результат детермінований і перевірюваний — тест або проходить після зміни, або ні, а diff видно очима. Але «відносно» не означає «сліпо». Модель може при рефакторингу непомітно послабити перевірку (замінити точну асерцію на присутність елемента) або втратити . Тому будь-який AI-рефакторинг проходить ту саму верифікацію, що й будь-який AI-вивід: прочитати diff критично, прогнати, і — головне — переконатися, що тест досі червоніє, коли фічу зламано (див. Верифікація результатів AI).
Self-healing локатори і їхні ризики
Self-healing локатори () — це механізм, коли тестовий інструмент, не знайшовши елемент за основним селектором, не падає одразу, а намагається знайти «той самий» елемент за іншими ознаками (текст, ARIA-роль, сусідні вузли, позиція) і продовжити прогін. Це фіча низки комерційних платформ (Testim, Mabl, testRigor) і опенсорсних надбудов (Healenium для Selenium). У Playwright тихого самозагоєння під час прогону немає — ставку зроблено на стабільні локатори; натомість станом на липень 2026 він має окремого Healer-, який після падіння не «лікує» тест мовчки, а пропонує патч локатора на рев'ю людині.
Спокуса зрозуміла: після кожної зміни верстки менше червоних , менше ручної правки локаторів. Але для QA тут ховається концептуальний конфлікт, і його треба вміти сформулювати на співбесіді:
Сенс тесту — впасти, коли застосунок несподівано змінився. Self-healing прямо цьому протидіє. Якщо кнопку «Оплатити» перейменували на «Купити», це могло бути свідоме рішення продукту — а могла бути й . Самовідновлення тихо «підлікує» локатор і зробить білд зеленим в обох випадках, і другий — це пропущений баг під виглядом успіху.
Конкретні :
- Маскування регресій — елемент зник чи змінився через баг, а тест «загоївся» на схожий і не помітив.
- Загоєння на неправильний елемент — на сторінці дві схожі кнопки, евристика вибрала не ту; тест зелений, але перевіряє не те.
- Недетермінізм — рішення про «схожість» імовірнісне, тож той самий тест може лікуватися по-різному в різних прогонах, додаючи новий шар флаку замість прибрати старий.
- Тихий дрейф — локатори повільно розходяться з реальним DOM, і ніхто цього не бачить, доки все не розсиплеться разом.
Здорова позиція: self-healing прийнятний як підказка для людини («локатор ось-ось зламається, ось кандидат на заміну — підтвердь»), а не як тихе автопродовження зеленим. Фундамент усе одно той самий, що й без AI — стабільні локатори (data-testid, ARIA-ролі) як контракт із розробкою; це канон стратегії локаторів у розділі автоматизації, а механіку селекторів розібрано в главі DOM, селектори та події.
Варто знати, що ISTQB CT-GenAI ставить наголос мʼякше, і межа тут проходить по тому, що вважати дрібною зміною. Силабус перелічує Self-healing and adaptive tests серед корисних застосувань GenAI у регресійному тестуванні (§2.2.3) — але вигоду обмежує словами minor UI or API changes і small modifications, а в тому самому підрозділі ставить гейт із модальністю MUST: the testers must be aware that GenAI can make mistakes і The generated output must therefore be carefully checked, depending on the associated risk. Тобто тихого автопродовження зеленим канон теж не дозволяє — він дозволяє автокорекцію під перевіркою, пропорційною ризику. Це та сама позиція, що вище, тільки без різкості.
Оновлення тестів після зміни UI/API
Коли фіча свідомо змінилася, десятки тестів червоніють законно — їх треба привести у відповідність. AI тут прискорює, але за однієї умови: давайте йому diff зміни, а не змушуйте вгадувати. Модель не бачила ні старого, ні нового застосунку; здогад «як тепер виглядає форма» — це вигадка. А от diff PR-у застосунку, зміна в OpenAPI-специфікації чи DOM «до/після» — це факти, з якими вона працює предметно.
- Зміна API. Згодуйте diff OpenAPI або приклад нової відповіді — і модель оновить асерти на тіло, статуси, назви полів. Тут доречні контрактні перевірки схемою (валідація структури програмно), а не звірка полів очима.
- Зміна UI. Новий
data-testid, переміщений елемент, перейменована дія — з diff-ом розмітки AI оновить локатори й кроки швидко.
Але є критична пастка. AI з радістю «полагодить» тест так, щоб він проходив під новий стан застосунку — навіть якщо цей стан і є регресією. Оновити впалий тест, щоб він позеленів, і закрити тікет — найлегший шлях зробити баг невидимим. Рішення «нова поведінка правильна» чи «це баг» — не технічне й не для моделі; його ухвалює людина за вимогами. AI прибирає механічну рутину оновлення; питання інтенту лишається за вами.
AI-рев'ю в пул-реквесті
AI-рев'ю (від вбудованого в до ботів, що коментують ) працює у двох напрямках: рев'ю вашого тестового PR і рев'ю продуктового PR з погляду QA. У супроводі корисні обидва.
Що AI ловить добре — це механічні дефекти й запахи, які око проскакує на великому diff:
- забутий
awaitперед web-first асертом; - тавтологічні перевірки на кшталт
expect(true).toBeTruthy(); - хардвейти замість авторетраю;
- крихкі локатори за згенерованими класами;
- відсутність негативних сценаріїв там, де вони очевидні.
Чого AI не ловить — і чому він не заміняє людину-рев'юера: чи перевіряє тест правильний інваріант, чи відповідає очікуваний результат реальній вимозі, чи має зміна доменний сенс. Модель бачить форму коду, не його намір. Тому найнебезпечніший результат — зелене AI-рев'ю сприймають як гарантію якості: бот не знайшов зауважень, отже все добре. Ні: відсутність механічних зауважень не означає, що тести перевіряють те, що треба. AI-рев'ю — це швидкий перший фільтр, який знімає рутину з людини-рев'юера, а не gate, що її замінює; фінальне слово на PR лишається за інженером (інтеграцію таких перевірок у розібрано в розділі про Git і CI/CD).
Типові помилки
- AI сказав «це баг застосунку» — виглядає як готовий діагноз, а насправді модель за замовчуванням звинувачує продукт; часто винен крихкий тест або флак, і перевірити треба руками до заведення дефекту.
Timeout→ «збільш таймаут» — виглядає як фікс, а насправді таймаут маскує гонку чи реальну відсутність елемента; більший таймаут лише повільніше валиться.- Self-healing зробив білд зеленим — виглядає як стабільність, а насправді тест міг «загоїтися» на неправильний елемент або приховати регресію; сенс тесту — впасти на несподівану зміну.
- AI оновив упалий тест, він проходить — виглядає як приведення у відповідність, а насправді тест міг бути підігнаний під баг; правильність нової поведінки вирішують вимоги, не модель.
- Зелене AI-рев'ю в PR — виглядає як знак якості, а насправді бот перевіряє форму, а не те, чи тест ловить правильний інваріант.
- Кинув голий лог, отримав причину — виглядає як тріаж, а насправді без trace//мережі це вгадування; діагноз рівно такий, як контекст.
Підсумок
- AI у тріажі корисний рівно настільки, наскільки повний контекст: давайте йому артефакти прогону (trace, скріншот, мережу, стек), а не власний переказ із уже вбудованою гіпотезою.
- Червоний тест — це три різні речі: баг продукту, баг тесту, інфраструктура/флак. AI генерує гіпотезу; класифікацію підтверджуєте ви.
- Модель схильна прив'язуватися до симптому, звинувачувати застосунок і вигадувати зв'язний, але хибний root cause — гладкість діагнозу не є його правильністю.
- Self-healing локатори борються з самою метою тесту — падати на несподівану зміну; прийнятні як підказка людині, не як тихе автозагоєння зеленим.
- AI прибирає механічну рутину рефакторингу, оновлення й рев'ю, але рішення про інтент («нова поведінка правильна чи це баг») і фінальний gate лишаються за інженером.
Можливі питання
- «Тест упав. Як ви користуєтесь AI, щоб розібратися?» — інтерв'юер хоче почути про збір контексту (trace, скріншот, мережа, логи), а не «кидаю лог — він каже причину». Сильна відповідь згадує, що AI дає гіпотезу, яку ви перевіряєте.
- «AI сказав, що це баг застосунку. Що робите далі?» — пастка на різницю фейл ≠ баг. Правильно: не заводжу дефект наосліп, спершу відтворюю руками / перевіряю бекенд, класифікую баг тесту vs баг продукту vs флак.
- «Що думаєте про self-healing локатори?» — перевірка зрілості. Очікують названий конфлікт: самовідновлення суперечить меті тесту падати на зміну; ризик маскування регресій і загоєння на не той елемент; прийнятно лише як підказка.
- «AI переписав/оновив тест, він зелений. Мерджимо?» — перевірка на автоматизаційне упередження. Сильна відповідь: спершу переконуюся, що тест червоніє при зламаній фічі, і що оновлення не підігнане під регресію.
- «Чи можна довіряти AI-рев'ю в PR замість людини?» — очікують межу: AI ловить механічні дефекти й запахи, але не доменну коректність та інваріант; це фільтр, не gate.
На що дивиться інтерв'юер: чи трактуєте ви AI-діагноз як гіпотезу на перевірку, а не як вирок; чи тримаєте різницю «фейл тесту ≠ баг продукту»; чи усвідомлюєте, що зелене (загоєний локатор, оновлений тест, чисте AI-рев'ю) не дорівнює правильному.
Джерела
Тріаж фейлу: артефакти як контекст для AI
- Playwright — Trace viewer — що саме дає трейс як найбагатший артефакт падіння: дії, DOM-снапшоти, мережа й консоль.
- Claude Code Docs — Best practices for Claude Code — як формулювати задачу на розбір: симптом, імовірне місце й те, як виглядає «полагоджено», з вимогою лікувати корінь, а не глушити помилку.
- ISTQB CT-GenAI Syllabus v1.1 — покращене репортування дефектів і аналіз як канонічна активність, яку GenAI підтримує.
Фейл ≠ баг: де AI помиляється в діагнозі
- ISTQB CTAL-TAE Syllabus v2.0 — джерельна форма «фейл ≠ баг»: окремий статус для дефекту не в SUT, а в самому рішенні автоматизації, і процедура тріажу перед заведенням дефекту.
- ISTQB CT-AI Syllabus v2.0 — чому гладкий діагноз не є правильним: схильність до впевнених, але неправильних передбачень і проблема .
- ISTQB CT-GenAI Syllabus v1.1 — гейт із модальністю MUST:
GenAI can make mistakes, тож вивід перевіряють ретельно й пропорційно ризику. - Claude Code Docs — Best practices for Claude Code — пряма вимога
address the root cause, don't suppress the error, що б'є саме по «збільш таймаут».
- xUnit Test Patterns — Erratic Test — канонічні осі, за якими взагалі шукають патерн: середовище, підмножина тестів, повтор поспіль і паралельні .
- ISTQB CT-GenAI Syllabus v1.1 — «аналіз результатів прогону → пошук спільного» як канонічна вправа, а не самодіяльність.
- ISTQB CT-AI Syllabus v2.0 — межа висновку: кластер не є причиною, а модель схильна видати впевнене пояснення там, де його немає.
- Playwright — Best Practices — чому саме такий рефакторинг: ставка на стабільні локатори й web-first асерти замість ручних пауз.
- Playwright — Writing tests — механіка під заміною: дієздатності знімає потребу в хардвейтах, а асинхронні матчери потребують
await. - Claude Platform Docs — Prompting best practices — пряма заборона правити чи видаляти тести: саме так рефакторинг «непомітно послаблює перевірку».
- Claude Code Docs — Best practices for Claude Code — гейт на результат: перевіркою може бути прогін набору чи дифф проти , і без неї віддавати не можна.
Self-healing локатори і їхні ризики
- ISTQB CT-GenAI Syllabus v1.1 — джерело обох цитат підрозділу: самовідновні тести серед корисних застосувань, але з обмеженням
minor UI or API changesі MUST-гейтом на перевірку виводу. - Playwright MCP — офіційний репозиторій (README) — термін
self-healing testsу офіційному тексті інструмента, поряд із дослідницькою автоматизацією й довгими автономними воркфлоу. - Playwright — Best Practices — альтернатива самозагоєнню: стабільні рольові й user-facing локатори як контракт із розробкою.
- ISTQB CT-AI Syllabus v2.0 — звідки береться новий шар флаку: рішення про «схожість» імовірнісне, тож ті самі входи не завжди дають той самий вихід.
Оновлення тестів після зміни UI/API
- Claude Platform Docs — Prompting best practices — пряма заборона
It is unacceptable to remove or edit tests: саме так упалий тест «підганяють» під регресію. - ISTQB CT-GenAI Syllabus v1.1 — аналіз змін коду як канонічна активність GenAI і той самий гейт: вивід перевіряють пропорційно ризику.
- Claude Code Docs — Best practices for Claude Code — чому дифф обов'язковий на вході: що точніші інструкції й конкретніший контекст, то менше виправлень і менше вигадок.
- Claude Code Docs — Best practices for Claude Code —
adversarial review stepі його чесна межа: рев'юер, якого просили знайти прогалини, повідомить їх навіть коли робота добра. - Playwright — Writing tests — приклад механічного дефекту з джерельною опорою: асинхронні матчери потребують
await, а забутийawaitпроковтує помилку. - Claude Code Docs — Run Claude Code programmatically (headless) — лінтер-рецензент на дифі PR як штатний сценарій неінтерактивного прогону.
- ISTQB CT-AI Syllabus v2.0 — чому це не gate: другу систему як оцінювача слід використовувати обережно, бо вона відтворює ті самі упередження й помилки.
Що таке тріаж червоного прогону і чому якість AI-діагнозу впирається саме в контекст?
(triage) — первинне сортування впалих тестів: швидко зрозуміти, що зламалося й куди копати, ще до глибокого розбору. AI не має власного доступу ні до вашого CI, ні до екрана, ні до стану бекенду — він працює виключно з тим шматком тексту, який ви вставили в . Тому діагноз виходить рівно такої якості, як набір фактів, що ви передали: одне слово «таймаут» дасть здогад, а trace із мережею й DOM — предметний напрямок. Порівняння просте: просити модель назвати причину за голим рядком помилки — те саме, що вимагати діагноз від лікаря за реплікою «болить». На співбесіді middle-рівня тут і видно слабкого кандидата: «кидаю лог, він каже причину» звучить як тріаж, а насправді це вгадування.
Які артефакти падіння варто передавати AI і чому голого повідомлення помилки замало?
Повідомлення помилки — лише верхівка: воно каже тип винятку й рядок, але не показує, що було на екрані й чи взагалі дійшов запит до бекенду. Інформативний набір складають (який виклик упав), , що не зматчився (чого тест не знайшов на сторінці), моменту падіння (реальний стан екрана), trace або відео (послідовність кроків, мережа, , DOM-снапшоти), HAR мережевих запитів (чи прийшла відповідь, який статус, що в тілі) і серверні логи (виняток на бекенді, correlation id). Найбагатший з них — trace: він єдиний зшиває дію, стан сторінки й мережу в одну картину. У Playwright цей архів збирається автоматично, наприклад опцією trace: 'on-first-retry', яка пише лише для повторного прогону впалого тесту. Що ширший контекст, то менше моделі лишається домислювати.
Чому не варто давати AI власний переказ падіння замість сирих фактів прогону?
Бо переказ уже несе вашу гіпотезу, а модель охоче до неї прив'язується й підтверджує те, що ви й так підозрювали. Напишете «впав, бо бекенд віддав не те» — AI підхопить рамку й будуватиме пояснення навколо неї, навіть якщо насправді винен крихкий локатор. Сирий артефакт (стек, trace, HAR) такого упередження не містить: він змушує модель відштовхуватися від того, що реально сталося, а не від вашої версії. Практичний висновок: у промпт кладіть факти прогону, а власний здогад лишайте наостанок або взагалі притримайте, поки не побачите незалежну гіпотезу. Це той самий порядок, що й у ручному тріажі, — спершу спостереження, потім висновок.
Червоний тест має три різні причини. Назвіть їх і поясніть, чому їх дорого плутати.
Падіння тесту означає одне з трьох, і кожне лікується інакше. Перше — баг продукту: застосунок справді працює неправильно, і саме заради цього тест існує. Друге — баг тесту: крихкий локатор, загублений await, гонка всередині самого тесту, крок, що відстав від зміненого UI; продукт при цьому здоровий. Третє — інфраструктура або : моргнуло оточення, впав сусідній сервіс, перехопив паралельний . Плутати їх дорого, бо реакції протилежні: на баг продукту заводять дефект, баг тесту лагодять у своєму коді, а стабілізують ізоляцією й ретраями. Найдорожча помилка — завести дефект на здоровий продукт: це спалює довіру команди до всього набору тестів.
Як саме AI помиляється, коли ставить діагноз падінню?
Модель видає найправдоподібніший текст, а не найправильніший, і має три впізнавані патерни хиб. Прив'язка до симптому: побачивши Timeout, вона радить збільшити , хоча час спливає і при реальній відсутності елемента, і коли тест чекає не на те. Звинувачення застосунку за замовчуванням: фраза «схоже, у продукті баг» правдоподібна, тож AI пише її навіть тоді, коли винен тест. Вигаданий root cause: модель складає струнку історію причини, що бездоганно лягає на лог, але може не мати з реальністю нічого спільного. Спільний корінь усіх трьох — гладкість формулювання не корелює з його правильністю. Тому AI-діагноз завжди трактують як гіпотезу на перевірку, а не як вирок.
AI побачив Timeout і радить збільшити таймаут. Чому це небезпечна порада?
Бо таймаут — це симптом із кількома різними причинами, а більший ліміт лікує лише одну з них. Час спливає, коли елемент реально не з'явився через баг продукту, коли тест чекає не на той стан через гонку в собі, і коли оточення просто повільне. У перших двох випадках збільшення таймауту нічого не лагодить — воно лише змушує тест валитися повільніше, зате маскує справжню проблему під виглядом «стабілізації». Особливо шкідливо це з гонкою: замість перейти на web-first очікування правильного стану команда роздуває таймаут, і флак повертається за кілька тижнів. Правильна реакція — з'ясувати, чого саме тест не дочекався, а не наосліп додавати секунди.
Де в аналізі флаку AI приносить найбільше чесної користі?
У пошуку патерну по великому масиву падінь, який людське око не охоплює. Один флакі-фейл інженер розбере й сам, а от закономірність у сотні прогонів — які тести, коли, на яких воркерах, у якому оточенні — руками не побачиш. Тут LLM сильна за своєю природою: вона добре підсумовує й кластеризує накидані дані, тож згодуйте їй історію падінь і попросіть згрупувати за спільними ознаками. На виході — напрямок пошуку: «ці п'ять валяться разом на одному воркері», «ця група червоніє тільки вночі». Це економить години читання логів, але саме напрямок, а не готовий вирок — межу треба тримати чітко.
Тест червоніє лише вночі, лише на воркері N або лише в CI. Про що зазвичай сигналить кожен патерн?
Це класичні кластери, кожен зі своїм типовим коренем. «Лише вночі» майже завжди вказує на таймзону чи межу доби в даних — тест переступає північ або рахує «сьогодні» не в тому поясі. «Лише на воркері N при паралельному запуску» — конфлікт за спільними тест-даними: два потоки правлять один акаунт чи запис. «Зелений локально, червоний лише в CI» — headless-таймінги, повільніше оточення, інший стан кешу. «Серія тестів валиться після одного конкретного» — протікання стану й порушена ізоляція: попередній тест лишив по собі сміття. Важливий нюанс: усе це кластери-підказки, а не діагнози — чому саме воркер 3 чи саме ніч, доводите ви перевіркою.
Чому кажуть, що AI групує симптоми, а не встановлює причину?
Бо кластеризація — це спостереження про форму падінь, а не доведений причинно-наслідковий зв'язок. «Ці тести падають на воркері 3» — правдиве угруповання, але воно не пояснює, чому саме там: спільний акаунт, конфлікт портів, брак ресурсів на цій машині — версій багато. Модель бачить кореляцію в даних, які ви їй дали, і чесно її називає, проте механізм за кореляцією вона не перевіряла й перевірити не може. Якщо прийняти кластер за причину, полагодите не те й патерн повернеться. Тому AI дає напрямок розкопок, а сам діагноз ви підтверджуєте — повторним прогоном, читанням логів воркера, зазиранням у дані.
Чому рефакторинг тестів вважають відносно безпечною задачею для AI?
Бо більшість рефакторингу — механічні трансформації з детермінованим і перевірюваним результатом. Винесення повторюваного блоку в , чистка дублювання, перейменування, заміна застарілого патерну на сучасний — після кожної такої зміни тест або проходить, або ні, і diff читається очима. Класика — масова заміна хардвейтів на web-first : await page.waitForTimeout(3000) перед перевіркою тексту перетворюється на await expect(locator).toHaveText(...) з авторетраєм. Петля зворотного зв'язку коротка: прогнав набір, подивився diff — і одразу ясно, чи не зламалося. Саме ця перевірюваність робить задачу зручною для моделі, на відміну від питань інтенту, де правильної відповіді в самому коді немає.
Який головний ризик AI-рефакторингу асертів, навіть якщо тест після нього зелений?
Модель може непомітно послабити перевірку — і зелений колір це замаскує. Типово: замість точної асерції на текст чи значення AI ставить перевірку на саму присутність елемента, або втрачає , який покривала стара версія. Тест проходить, diff виглядає чистим, але він тепер ловить менше, ніж ловив. «Відносно безпечно» не означає «сліпо мерджити»: AI-рефакторинг верифікують так само прискіпливо, як решту AI-виводу. Ключова перевірка — переконатися, що тест досі червоніє, коли фічу навмисно зламати; зелений на робочій фічі нічого не гарантує, якщо він зелений і на зламаній.
Що таке self-healing локатори і як вони працюють?
Self-healing локатори () — це коли після невдачі основного селектора інструмент не зупиняє прогін, а підбирає елемент-кандидат за додатковими ознаками — текстом, ARIA-роллю, сусідніми вузлами, позицією — і йде далі. Мета — менше червоних і менше ручної правки локаторів після кожної зміни верстки. Таке вміють комерційні платформи на кшталт Testim, Mabl і testRigor, а для Selenium є опенсорсний Healenium. Playwright тихого загоєння під час прогону не робить: його філософія — стабільні локатори; окремий Healer- (станом на липень 2026) після падіння лише пропонує виправлення локатора на рев'ю людині. Важливо: рішення про «схожість» завжди евристичне, тобто імовірнісне.
Який концептуальний конфлікт між self-healing і самою метою тесту?
Тест і існує для того, щоб зупинити білд, коли застосунок змінився несподівано, — а самовідновлення якраз не дає йому цього зробити. Уявіть, що кнопку «Оплатити» перейменували на «Купити»: за цим може стояти свідоме рішення продукту, а може — . Механізм в обох випадках мовчки підхопить нову кнопку, і білд пройде; у другому випадку баг проїде під виглядом успіху. Тобто зникає рівно той сигнал, заради якого тест писали. На співбесіді очікують, що кандидат назве цей конфлікт словами, а не просто скаже «self-healing зручний»: зручність і є пасткою, бо вона купується ціною сліпоти до змін.
Назвіть конкретні ризики self-healing локаторів.
Їх чотири, і всі про приховану деградацію. Маскування регресій: елемент пропав через баг, але тест підхопив схожий і промовчав. Загоєння на хибний елемент: із двох близьких кнопок евристика взяла не ту — прогін зелений, а перевіряється не те. Недетермінізм: «схожість» оцінюється імовірнісно, тож одне й те саме падіння в різних прогонах загоюється по-різному — до старого флаку додається новий. Тихий дрейф: локатори крок за кроком віддаляються від реального DOM, і цього ніхто не бачить, доки не розсиплеться все одразу. Спільна риса — усі чотири ховаються за зеленим кольором, тому їх важко зловити без окремого контролю.
Як тоді можна вбудувати self-healing, щоб він не шкодив?
Прийнятна форма — підказка людині, а не тихе автопродовження зеленим. Тобто інструмент має право сказати «локатор ось-ось зламається, ось кандидат на заміну — підтвердь», але не має права мовчки перемкнутися на інший елемент і зарахувати білд як успішний. У першому випадку рішення лишається за інженером, який звірить кандидата з реальністю; у другому механізм сам виносить вирок, до якого не має компетенції. Фундамент при цьому той самий, що й без AI, — стабільні локатори (data-testid, ARIA-ролі) як контракт із розробкою. Self-healing у здоровій конфігурації доповнює цей контракт сигналом про дрейф, а не заміняє його евристикою. Корисно знати й позицію ISTQB CT-GenAI: силабус подає self-healing серед корисних застосувань GenAI, але обмежує вигоду minor UI or API changes і в тому ж підрозділі вимагає перевіряти згенерований вивід пропорційно (must be carefully checked, depending on the associated risk) — тобто до того самого висновку приходить мʼякшим тоном.
Як AI прискорює оновлення тестів після зміни UI чи API і за якої умови?
Коли фіча свідомо змінилася, десятки тестів червоніють законно, і привести їх у відповідність — механічна рутина, з якою модель справляється швидко. Умова одна: давати їй diff зміни, а не змушувати вгадувати. Ні старої, ні нової версії застосунку модель не бачила, тому її уявлення про те, «як тепер виглядає форма», — чиста вигадка. А от diff PR-у, зміна в OpenAPI-специфікації чи розмітка «до/після» — з такими фактами вона працює предметно, а не з уяви. На зміні API згодуйте новий приклад відповіді або diff схеми — і AI оновить асерти на статуси, тіло, назви полів (тут доречні контрактні перевірки схемою, а не звірка полів очима). На зміні UI новий data-testid чи переміщений елемент з diff-ом розмітки оновлюються так само швидко.
Яка головна пастка при оновленні впалого тесту руками AI?
Модель охоче підганяє тест під поточну поведінку застосунку — включно з поведінкою, що з'явилася через баг. Оновити впалий тест до зеленого й закрити тікет — найлегший спосіб зробити баг невидимим: перевірка тепер узгоджена зі зламаною поведінкою й більше на неї не скаржиться. Вердикт «так і задумано» чи «це регресія» — не технічне питання, і виносить його людина, звіряючись із вимогами продукту. AI знімає механічну частину (переписати локатори, підправити асерти), але питання інтенту лишається за інженером. Тому оновлений тест обов'язково звіряють із вимогою, а не просто радіють, що він позеленів.
Що AI-рев'ю в пул-реквесті ловить добре, а що — принципово ні?
Добре ловить механічні дефекти й запахи, що на великому diff проскакують повз око: await, забутий перед web-first асертом, тавтології типу expect(true).toBeTruthy(), хардвейти там, де мав бути авторетрай, локатори на згенерованих класах, брак очевидних негативних сценаріїв. Це швидкий перший фільтр, що знімає рутину з людини-рев'юера. Чого AI не бачить: чи той інваріант перевіряє тест, чи збігається очікування з реальною вимогою, чи має зміна сенс у домені. Модель читає форму коду, а не його намір. Тому AI-рев'ю працює як фільтр, а не як gate, і фінальне слово на PR лишається за інженером.
Чому «зелене AI-рев'ю» небезпечно трактувати як гарантію якості?
Бо відсутність механічних зауважень і коректність тесту — це різні речі. Бот не знайшов забутих await і крихких локаторів — це означає лише, що форма коду чиста, а не що тест перевіряє те, що треба. Тест може бути бездоганний синтаксично й водночас асертити не той інваріант, звірятися з хибним очікуванням чи взагалі не мати доменного сенсу — усе це AI-рев'ю пропустить. Найгірший сценарій, коли команда сприймає зелений вердикт бота як «якість підтверджено» й вимикає людський розбір. Правильна рамка: чисте AI-рев'ю прибирає шум і економить час рев'юера, але не переносить на нього відповідальність — її несе інженер, що апрувить PR.
Сформулюйте загальне правило роботи з будь-яким AI-діагнозом у супроводі тестів.
AI генерує гіпотези — підтверджуєте їх ви. Хоч що модель сказала про падіння, флак, рефакторинг чи оновлення тесту, це кандидат на перевірку, а не встановлений факт: перевірка гіпотези «це баг бекенду» коштує один curl, а завести дефект без цієї перевірки — антипатерн. Наскрізна дисципліна — розрізняти форму й суть: гладкий діагноз не дорівнює правильному, зелений колір (загоєний локатор, оновлений тест, чисте рев'ю) не дорівнює правильному тесту. Практично це означає завжди зводити AI-вивід до перевірюваної дії: повторний прогін, ручне відтворення кроку, зазирання в мережу чи БД, перевірка, що тест червоніє на зламаній фічі. AI прибирає рутину, але класифікацію, інтент і фінальний gate тримає інженер.
Три ситуації супроводу, де AI або економить годину , або впевнено веде не туди: як один і той самий міняє діагноз залежно від контексту, як класифікувати падіння замість вірити «це баг застосунку», і як self-healing перетворює на зелений . Скрізь — що дивитися і де межа довіри.
Кейс 1. Один фейл, два промпти: чому контекст вирішує все
Уранці впав тест оформлення замовлення. Помилка сама по собі скупа:
TimeoutError: locator.click: Timeout 30000ms exceeded.
Call log:
- waiting for getByRole('button', { name: 'Оплатити' })
Поганий промпт — кинути AI рівно цей рядок і спитати «чому впало». Модель відповість найправдоподібнішим текстом: «схоже, кнопка вантажиться повільно — збільште таймаут» або «ймовірно, баг у застосунку, кнопка не відрендерилась». Обидва діагнози звучать гладко й обидва можуть бути хибними: жодного факту про реальний стан екрана в промпті не було, тож це вгадування, а не тріаж.
Хороший промпт — додати артефакти прогону з trace. Тоді в контексті з'являються мережа й DOM-снапшот моменту падіння:
Network (з trace):
POST /api/cart/checkout → 200 OK
GET /api/user/profile → 401 Unauthorized
DOM-снапшот на момент падіння:
<div class="session-expired-modal">Сесія завершилася. Увійдіть знову.</div>
Тепер картина інша: кнопки «Оплатити» немає не тому, що вона повільна, а тому що поверх сторінки — модалка простроченої сесії через 401. Збільшення тут не допомогло б ніколи. AI з таким контекстом дасть предметну гіпотезу («токен протух до кроку оплати»), яку легко перевірити.
Що дивитися і чому:
- Голе повідомлення помилки несе тип і рядок, але не стан екрана.
Timeoutна кліку однаково виглядає і коли елемент повільний, і коли його перекрила модалка, і коли його взагалі немає через баг. Розрізняє ці випадки саме DOM-снапшот і мережа з trace. 401у мережі — це напрямок, а не вирок. Він каже, куди копати (автентифікація перед оплатою), але чому саме протух токен — короткий TTL, гонка з рефрешем, кривий сетап тесту — з'ясовуєте ви. AI звузив пошук з усієї сторінки до одного запиту; діагноз усе одно за вами.- Переказ отруює діагноз. Якби в промпті було «кнопка оплати не завантажується, здається, баг рендеру», модель прив'язалася б до рендеру й могла б не помітити
401. Сирий trace такого упередження не має.
Кейс 2. «AI сказав, що це баг застосунку» — класифікація по кроках
Частий ранковий діалог: інженер кинув боту лог 500, той відповів «схоже на баг бекенду», і виникає спокуса завести дефект і закрити тікет. Але 5xx міг тригернути будь-хто, тож спершу — класифікація. для трьох причин червоного:
| Спостереження | Імовірна причина | Перша перевірка |
|---|---|---|
500 відтворюється валідним запитом через curl | Баг продукту | Стектрейс у логах сервера → який контролер упав |
500 не відтворюється руками, падає лише тест | Баг тесту | Що реально пішло в запиті: токен, змінна, середовище |
Масові 502/503/504 одразу після релізу | Інфра/деплой | Чи середовище взагалі піднялося |
Зелено поодинці, 500 лише під паралелізмом | Флак/ізоляція | Спільні дані, гонки, rate limit між воркерами |
Найдешевша перевірка — відтворити той самий запит руками, а не вірити на слово:
# той самий виклик, що впав у тесті — валідним запитом
curl -i -X POST https://staging.example.com/api/orders \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"productId": 42, "qty": 1}'
- Відтворюється валідним запитом → кандидат на баг бекенду, і стектрейс у логах це підтвердить.
- Не відтворюється, а тест усе одно падає → підозра зміщується на тест: не підставилась змінна, протух токен, крива , не те середовище.
Що дивитися і чому:
- AI звинувачує застосунок за замовчуванням. «Схоже на баг продукту» — правдоподібна фраза, яку модель пише й тоді, коли винен . Це найдорожча помилка тріажу: дефект на здоровий продукт палить довіру команди.
- Гіпотеза коштує один
curl. Заявляти причину без перевірки — антипатерн; «стектрейс указує на конкретний контролер» варте рівно стільки, скільки під ним доказів. 500на завідомо кривому вводі — окремий дефект бекенду. Навіть якщо тригер прийшов від тесту, добре спроєктований сервер мав відповісти400/422, а не впасти. Тобто винних тут може бути двоє одночасно.
Кейс 3. Self-healing проти стабільного локатора: як регресія стає зеленою
Розробники перейменували кнопку кошика й заразом випадково прибрали в неї обробник кліку — покупку зламано. Дивимось, як на це реагують два підходи.
import { test, expect } from '@playwright/test';
// Стабільний локатор: контракт із розробкою через data-testid
test('кнопка "Купити" додає товар у кошик', async ({ page }) => {
await page.goto('https://shop.example.com/product/42');
await page.getByTestId('add-to-cart').click();
await expect(page.getByTestId('cart-badge')).toHaveText('1');
});
Якщо data-testid на місці, але обробник зник — тест чесно червоніє на cart-badge: лічильник кошика лишився 0. Це і є сенс тесту — впасти на несподівану зміну поведінки. Регресію спіймано до продакшену.
Тепер уявімо той самий сценарій під платформою із self-healing, де локатор прив'язаний до тексту кнопки:
Крок: click button "Додати в кошик"
⚠ основний селектор не знайдено (кнопку перейменували на "Купити")
✓ self-healing: знайдено схожий елемент за роллю/позицією → "Купити"
✓ клік виконано, крок пройдено
Результат білда: PASSED
Локатор «загоївся», клік формально відбувся — але обробник зламано, товар у кошик не потрапив, а білд зелений. Самовідновлення прибрало рівно той сигнал, заради якого тест існував.
Що дивитися і чому:
- Self-healing протидіє меті тесту. Перейменування кнопки могло бути свідомим рішенням продукту, а могло бути регресією; механізм робить білд зеленим в обох випадках, і другий — це пропущений баг під виглядом успіху.
- Загоєння буває на неправильний елемент. Якби поруч була ще одна кнопка, евристика могла вибрати не ту — тест лишався б зеленим, перевіряючи не те. Рішення про «схожість» імовірнісне, тож ще й недетерміноване між прогонами.
- Здорова конфігурація — підказка, не автопродовження. Прийнятний варіант: «локатор ось-ось зламається, кандидат на заміну — "Купити", підтвердь». Тоді інженер звірить зміну з вимогою, а не бот винесе вирок, до якого не має компетенції.
- Фундамент той самий, що й без AI. Стабільні локатори (
data-testid, ARIA-ролі) як контракт із розробкою надійніші за будь-яку евристику схожості; self-healing у кращому разі доповнює їх сигналом про дрейф, а не заміняє.
Тріаж і контекст для AI
- Розумію, що AI не бачить мого CI, екрана й бекенду — його діагноз рівно такий, як факти, вставлені в .
- Знаю набір інформативних артефактів падіння: , , що не зматчився, , trace/відео, HAR, серверні логи.
- Можу пояснити, чому trace — найбагатший артефакт: він зшиває дію, стан DOM і мережу в одну картину.
Фейл ≠ баг
- Тримаю три причини червоного тесту: баг продукту, баг тесту, інфраструктура/ — і знаю, що реакція на кожну різна.
- Розумію, чому завести дефект на здоровий продукт — найдорожча помилка: вона палить довіру команди до тестів.
- Знаю три патерни хиб AI: прив'язка до симптому, звинувачення застосунку за замовчуванням, вигаданий root cause.
- Тримаю правило: AI дає гіпотезу, класифікацію підтверджую я — повторним прогоном, ручним відтворенням,
curlдо бекенду.
Флакі та патерни
- Розумію, де AI сильний у : кластеризація патерну по сотні прогонів, який око не охоплює.
- Знаю типові кластери: «лише вночі» → таймзона, «воркер N» → спільні дані, «лише в CI» → headless-таймінги, «після одного тесту» → протікання стану.
- Можу пояснити межу: AI групує симптоми, а причину за кластером доводжу я.
Рефакторинг і оновлення тестів
- Розумію, чому механічний рефакторинг відносно безпечний для AI: результат детермінований і перевірюваний diff-ом та прогоном.
- Пам'ятаю : AI може непомітно послабити асерцію — тому перевіряю, що тест досі червоніє на зламаній фічі.
- Можу пояснити умову оновлення тестів: давати AI diff зміни (PR, OpenAPI, DOM «до/після»), а не змушувати вгадувати.
- Тримаю пастку: AI підганяє впалий тест під новий стан навіть якщо той стан — ; рішення про інтент за людиною.
Self-healing локатори
- Формулюю конфлікт: мета тесту — впасти на несподівану зміну, а self-healing тихо це загоює.
- Знаю чотири ризики: маскування регресій, загоєння на не той елемент, недетермінізм, тихий дрейф локаторів.
- Тримаю здорову позицію: self-healing прийнятний як підказка людині, не як тихе автопродовження зеленим.
AI-рев'ю в PR
- Знаю, що AI-рев'ю ловить: забутий
await, тавтології, хардвейти, крихкі локатори, брак очевидних негативних сценаріїв. - Розумію, чого воно не ловить: правильність інваріанта, відповідність вимозі, доменний сенс.
- Можу пояснити, чому зелене AI-рев'ю — не гарантія якості, а лише фільтр, і чому фінальний gate лишається за інженером.
Квіз
Перед стартом
- Питань: 15
- Поріг «зараховано»: ≥70% правильних відповідей.
- Результат впливає на прогрес; завалені питання підуть у чергу повторення.
- Квіз впливає на компліт теми: тема стає «пройдено», лише коли прочитано теорію І квіз складено на ≥70%.
Питання
Тріаж (triage) падіння — що це і чому для AI критичний контекст?