vyvchy
    Теми розділу

    07 · Інструменти автоматизації

    Playwright: дебаг, trace viewer і репортинг

    Зміст

    Червоний тест у CI — це не повідомлення про баг, а квиток на розслідування. Локально в тебе є браузер під рукою: можна поставити паузу, поклацати, подивитися DOM. У CI немає нічого, крім файлів, які прогін по собі лишив, — і саме там падає та частина тестів, яка «локально ж проходила». Тому інструмент дає два різні класи засобів: живі (Inspector, UI mode) і post-mortem-засоби (trace viewer), де ти читаєш запис уже завершеного прогону. Плюс третій шар — репортери, які перетворюють прогін у щось придатне для читання людиною і машиною.

    Цю главу можна пропустити при першому проході: щоб писати тести, вона не потрібна. Але тут закінчуються питання «а чому в CI падає, а локально ні» — і починається різниця між «перезапустив, і воно позеленіло» та «знаю, на якій дії, з яким локатором і чому». Таксономія падінь, політика і звітність як дисципліна живуть у розділі «Автоматизація тестування»; тут — механіка конкретного інструмента.

    Два режими: наживо і після факту

    Inspector — це GUI, у якому тест виконується покроково: видно поточну дію, можна правити наживо, підбирати локатори й читати логи придатності до дії (actionability). Відкривається прапорцем --debug.

    Головне про цей розуміють не одразу: він не просто відкриває вікно, а міняє конфігурацію прогону. Браузер запускається у видимому режимі, а стає нульовим — тобто «без таймауту». Ось звідки береться улюблена : під --debug тест по таймауту не падає, бо чекає скільки завгодно, а в CI на тому самому кроці валиться по штатному таймауту. Це не «локально стабільніше» — це інші налаштування.

    npx playwright test --debug   # Inspector: видимий браузер + таймаут 0
    npx playwright test --ui      # UI mode: time travel, watch-режим

    Проклацувати кожну дію, щоб дійти до цікавого місця, не потрібно: page.pause() ставить усередині тесту, і після натискання «Resume» виконання зупиниться саме на ній.

    await page.getByRole('button', { name: 'Checkout' }).click();
    await page.pause(); // далі — руками в Inspector

    Найцінніша частина Inspector — не покрокове виконання, а лог придатності. До моменту, коли інструмент став на паузу перед кліком, він уже виконав перевірки, і в лозі видно: чи локатор узагалі знайшов елемент, чи елемент видимий, увімкнений і стабільний, чи була прокрутка до нього. Якщо придатності досягти не вдалося, дія показується як pending — не як помилка. Це і є той розріз, який плутають найчастіше: «локатор не той» і «елемент ще не готовий» лікуються по-різному, а в звіті обидва спершу виглядають як таймаут. Самі критерії придатності — в главі про перевірки й автоочікування.

    Поруч є ще два живі інструменти. Зі змінною PWDEBUG=console у DevTools зʼявляється обʼєкт playwright, тож прямо в паузі можна дивитися DOM і мережу браузера. А розширення для VS Code при падінні показує очікуване, отримане й повний call log просто в редакторі; у режимі Show Browser сесія браузера перевикористовується між прогонами.

    post-mortem-режим — інший за природою. Trace viewer читає записаний (trace) уже після того, як скрипт відпрацював, і придуманий саме для падінь у CI, куди дебагером не залізеш.

    Локально, відтворюється

    Локально, треба оглянути сюїту

    Тільки в CI

    Тест упав

    Де впав?

    Inspector: --debug
    page.pause, лог придатності

    UI mode: --ui
    watch + авто-трейс

    Трейс з артефактів
    trace viewer

    Причина: локатор, готовність, дані

    Локально, відтворюється

    Локально, треба оглянути сюїту

    Тільки в CI

    Тест упав

    Де впав?

    Inspector: --debug
    page.pause, лог придатності

    UI mode: --ui
    watch + авто-трейс

    Трейс з артефактів
    trace viewer

    Причина: локатор, готовність, дані

    UI mode: time travel і watch-режим

    UI mode — окремий режим, а не косметика над --debug: він дає перегляд, запуск і розбір тестів із time travel та watch-режимом. Запускається npx playwright test --ui.

    Що там реально корисно:

    • Actions — для кожної дії видно, який локатор використано і скільки вона тривала.
    • Повний лог того, що інструмент робить під капотом: прокрутка до елемента, очікування видимості, увімкненості й стабільності, потім сама дія. Той самий лог придатності, що в Inspector.
    • Errors — повідомлення про помилки, а на таймлайні червона лінія на місці падіння.
    • Консоль, у якій логи браузера й логи тестового файла позначені різними іконками. Дрібниця, яка економить хвилини: одразу видно, чиє це повідомлення — застосунку чи твого console.log.
    • Playground для локаторів — правиш локатор і бачиш, чи він щось знаходить у DOM-знімку.
    • Watch-режим — клік по іконці, і тест перезапускається на кожну зміну.

    Практична різниця з ручним записом трейсу названа в доці прямо: у режимі розробки трейс вмикають прапорцем --trace on, а UI mode трейсить кожен тест сам. Тобто окремо його вмикати не треба.

    І одне обмеження, яке варто знати до першого зіткнення: UI mode не враховує setup-тести, їх доводиться запускати вручну. Якщо проєкт логіниться setup-проєктом і кладе стан у файл — саме тут виникає «в UI падає, а в звичайному рані ні». Механіка setup-проєктів — у главах про фікстури й конфігурацію та автентифікацію й повторне використання стану.

    Що лежить у трейсі

    Трейс — це запис ходу виконання тесту, а не . Різниця принципова, тому варто перелічити, що всередині:

    • Дії — використаний локатор і тривалість кожної дії, з переходом уперед і назад у часі.
    • DOM-знімки для кожної дії: наводиш на дію — бачиш, як змінилася сторінка.
    • Помилки з таймлайном, де падіння позначене червоною лінією, і вкладка з вихідним кодом, яка показує сам рядок.
    • Мережа — усі запити прогону, з сортуванням за типом запиту, , методом, типом вмісту, тривалістю й розміром. Це той самий матеріал, з яким працює глава про перехоплення й мокання мережі, тільки постфактум.
    • Консоль — повідомлення браузера й тесту.
    • Метадані — браузер, розмір вікна, тривалість тесту.
    • Вкладення — зокрема діф зображень разом із фактичним і очікуваним скріншотами, якщо в прогоні були візуальні порівняння.

    Ще одна властивість, важлива для закритих середовищ: трейс завантажується повністю в браузері й нічого не передає назовні. Це самодостатній файл, який можна прикріпити до тікета: щоб його прочитати, дані нікуди вивантажувати не треба.

    Чому цього не заміняє скріншот падіння? Бо скріншот — один кадр стану, а причина зазвичай у послідовності: який локатор спрацював, скільки він чекав, що прийшло з мережі перед тим. Канон автоматизації дивиться на це так само: скріншоти й записи екрана — легітимне джерело даних, і зберігають їх саме для аналізу першопричини, поруч із логами SUT, логами фреймворку як аудиторським слідом і логами . У разі падіння рішення автоматизації має зберегти все, що потрібне для аналізу.

    Стратегії запису: чому не «трейс завжди»

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

    Тому канонічна розкладка така:

    ДеСтратегіяЩо отримуєш
    Локальна розробка--trace on або UI modeТрейс кожного прогону — вартість тут зазвичай не критична
    CItrace: 'on-first-retry'trace.zip для кожного тесту, який ретраївся
    CI, «щоб було»trace: 'on'Повний запис — і сповільнений прогін; дока радить так не робити

    Стратегія on-first-retry — не компроміс, а точне попадання: трейс потрібен рівно там, де тест уже впав, тож його пишуть на першому ретраї (retry) невдалого тесту. Наслідок, на який натикаються всі: якщо ретраїв у конфігурації немає, трейсів теж не буде — записувати нічого, бо ретраїв не сталося.

    Ретрай тут працює як прилад, а не як замазка: розводить три стани, а не два. passed — пройшов з першого разу; flaky — упав, але пройшов на повторі; failed — упав і на першому прогоні, і на всіх ретраях. Тест навіть бачить, що він на ретраї (testInfo.retry). Політика ретраїв — тема розділу «Автоматизація тестування», механіка засобами інструмента — глава про боротьбу з флаком.

    Конфігурація має рівні, які легко переплутати: опції самого ранера живуть на верхньому рівні, опції оточення тесту — в секції use. Штатний приклад із доки навмисно різнить локальний і CI-режим:

    // playwright.config.ts
    import { defineConfig } from '@playwright/test';
    
    export default defineConfig({
      forbidOnly: !!process.env.CI,      // забутий test.only валить білд у CI
      retries: process.env.CI ? 2 : 0,   // ретраї лише в CI
      use: {
        trace: 'on-first-retry',         // трейс лише на повторі впалого тесту
      },
    });

    Скріншоти й відео при падінні

    Для CI-падінь дока Playwright формулює вибір однозначно: використовуй trace viewer замість відео й скріншотів, бо трейс дає повний слід — таймлайн, DOM-знімки кожної дії з через DevTools, мережеві запити. Скріншот і відео відповідають на питання «що було видно», трейс — на питання «що відбувалося».

    Це не означає «скріншоти не потрібні». Вони лишаються там, де симптом треба показати людині, яка трейс не відкриє, і там, де зображення — це сам предмет перевірки: у візуальному тестуванні еталон, фактичний знімок і діф читають саме як вкладення трейсу. Аргумент вартості діє й тут: артефакти збирають на падінні або ретраї, а не на кожному зеленому прогоні.

    Репортери: людині, машині і CI

    Перше, що варто засвоїти: репортери (reporters) не взаємовиключні. Їх вмикають кілька одночасно — наприклад, читабельний вивід у термінал і машинний файл із результатами. І локальний набір свідомо відрізняється від CI-набору: локально дефолт — list (рядок на кожен тест), у CI — dot (один символ на успішний тест), щоб не заливати лог.

    РепортерЩо дає
    listРядок на кожен тест; дефолт локально
    lineОдин рядок про останній завершений тест плюс падіння в міру появи; для великих сюїт
    dotОдин символ на кожен успішний тест; дефолт у CI
    htmlСамодостатня тека зі звітом, яку можна віддати як вебсторінку
    jsonОбʼєкт з усією інформацією про прогін
    junitXML у стилі JUnit — формат обміну для CI-систем, а не звіт для людини
    blobУсі деталі прогону; головне призначення — злиття звітів шардів
    reporter: process.env.CI
      ? [['dot'], ['html'], ['junit']]   // людині, для перегляду, для CI
      : [['list']],

    blob варто розуміти окремо: це проміжний формат, з якого потім роблять будь-який інший звіт. Файли шардів кладуть в одну теку й зливають, а конфліктів імен немає, бо номер шарда входить у назву файла (report-<hash>-<shard_number>.zip). Детальніше про (sharding) — у главі про паралельний запуск.

    Allure — оглядово (ширше про звітність і тренди — у розділі «Автоматизація тестування»). Дві речі, які тут плутають постійно:

    • Історія й ретраї — різне. Ретраї — це повтори всередині одного прогону; історія — звʼязок між різними звітами. Механізм звʼязування — унікальний ідентифікатор тесту, тому перейменування тесту рве історію, і тренд починається з нуля.
    • Історія не зʼявляється сама. В Allure 2 теку history з попереднього звіту треба скопіювати в теку результатів перед генерацією нового — інакше кожен звіт буде першим у житті.

    Корисні й категорії: інструмент розводить Product errors (тест failed) і Test errors (тест broken), кожен результат належить рівно одній категорії, а кастомні правила матчаться першими й у порядку оголошення. Це той самий поділ «баг продукту чи баг тесту», тільки автоматизований у звіті.

    І рамка, яку варто тримати над усім інструментарієм. Логи звітом не є: вони дають деталі кроків, але не дають огляду результатів прогону. Звіт про прогрес (test progress report) за каноном must містити результати, інформацію про систему під тестом і опис оточення — у формі, придатній для конкретної аудиторії, і should публікуватися всім релевантним стейкхолдерам. Деталізація законно різниться залежно від отримувача, а тренди вимагають аналізу попередніх прогонів.

    Розбір фейлу в CI: від репорту до першопричини

    Головний факт, з якого випливає вся дисципліна артефактів: на ранерах GitHub кожен прогін іде на свіжій, щойно розгорнутій віртуальній машині, а кожна — у власному ранері або . Дані вільно ходять лише між кроками однієї джоби, бо вони на тому самому ранері. Практичний висновок жорсткий: якщо трейс не вивантажено артефактом, його немає. «Зайду на агент подивлюся» не існує як план.

    Далі — порядок, який перетворює червоний звіт у причину:

    flaky

    failed

    Так, а тест червоний

    Ні

    Так

    Червоний звіт

    Статус тесту

    Пройшов на ретраї
    трейс є саме за цей ретрай

    Упав на всіх спробах

    Чи падало раніше?
    історія й тренд

    Трейс: на якій дії,
    з яким локатором, скільки чекав

    Мережа, консоль, метадані:
    браузер і розмір вікна

    Фактичний = очікуваний?

    Дефект у самому рішенні
    автоматизації

    Крок і стан SUT
    у баг-репорт

    Упало все?

    Оточення недоступне,
    а не регресія

    flaky

    failed

    Так, а тест червоний

    Ні

    Так

    Червоний звіт

    Статус тесту

    Пройшов на ретраї
    трейс є саме за цей ретрай

    Упав на всіх спробах

    Чи падало раніше?
    історія й тренд

    Трейс: на якій дії,
    з яким локатором, скільки чекав

    Мережа, консоль, метадані:
    браузер і розмір вікна

    Фактичний = очікуваний?

    Дефект у самому рішенні
    автоматизації

    Крок і стан SUT
    у баг-репорт

    Упало все?

    Оточення недоступне,
    а не регресія

    Кілька кроків варті окремого слова.

    Статус — це вже половина діагнозу. flaky означає, що тест упав і пройшов на повторі: продукт, найімовірніше, живий, а проблема — у детермінованості тесту або даних. І трейс у тебе якраз є, бо on-first-retry записав саме цей повтор.

    Історія важливіша за один прогін. Канон радить тримати історію звітів, щоб збирати статистику про тести й з частими — це і є матеріал для трендів, і це ж спосіб відповісти на перше питання : чи таке падіння вже траплялося.

    Два вердикти, які легко переплутати. Якщо фактичний і очікуваний результати збігаються, а тест червоний — найімовірніше дефект у самому рішенні автоматизації, а не в продукті. А якщо впали всі тести, канон велить першою підозрою ставити недоступне оточення, а не масову регресію: перед тим як заводити тридцять багів, перевір, чи стенд узагалі піднявся. Зшити тестовий лог із логами системи допомагає кореляційний ідентифікатор (correlation ID, trace ID) — один наскрізний id на запит.

    Коли локально не відтворюється — перше питання не «який локатор», а чи падає тест, коли він єдиний у прогоні. Це найшвидший спосіб відділити взаємодію тестів між собою від справжнього дефекту; у каталозі нестабільних тестів цей клас так і називається — тести, що взаємодіють (Interacting Tests).

    Окремий клас — «тести не запустилися взагалі». Якщо в CI падає не , а старт браузера, розбирати трейс нічого: змінна DEBUG=pw:browser виводить логи запуску браузера, і дока радить її саме на помилках «Failed to launch browser». За замовчуванням браузери стартують headless, а видимий режим на Linux-агенті вимагає встановленого Xvfb (в офіційному Docker- й GitHub Action він уже є).

    Типові помилки

    • «Локально проходить, у CI падає по таймауту» — виглядає як капризи інфраструктури, а насправді ти ганяв тест під --debug, де таймаут дорівнює нулю. Локально він не падав не тому, що швидший, а тому, що йому дозволили чекати вічно.
    • «У UI mode тест червоний, у звичайному рані зелений» — виглядає як баг режиму, а насправді UI mode не враховує setup-тести: setup-проєкт, який логінить і кладе стан, треба запустити вручну.
    • «Увімкнули on-first-retry, а трейсів у CI немає» — виглядає як зламаний конфіг, а насправді трейс пишеться на ретраї: якщо ретраї не ввімкнені, записувати нічого.
    • «Є скріншот падіння — розберемось» — виглядає як діагностика, а насправді один кадр не каже, який локатор спрацював, скільки він чекав і що прийшло з мережі. Для аналізу першопричини потрібен слід, а не лише картинка.
    • «Артефакт не вивантажили, зайду на агент подивлюся» — виглядає як план, а насправді на ранерах GitHub прогін ішов на свіжій віртуальній машині, якої вже не існує.
    • «Перейменували тест — і тренд у звіті обнулився» — виглядає як баг звіту, а насправді історія звʼязує прогони за унікальним ідентифікатором тесту, і нова назва — це для звіту новий тест.
    • «Шардували прогін — отримали пʼять звітів замість одного» — виглядає як поломка, а насправді єдиний звіт — це окремий крок злиття blob-звітів, а не побічний ефект шардінгу.
    • «Тест червоний — значить, баг у продукті» — виглядає як логіка, а насправді якщо фактичний і очікуваний результати збігаються, дефект найімовірніше в самому рішенні автоматизації; а якщо впало все — питання передусім до оточення, не до продукту.

    Підсумок

    • Прапорець --debug міняє конфігурацію, а не лише відкриває вікно: видимий браузер і нульовий таймаут. Значна частина розходжень «локально/CI» — саме тут.
    • Живий і post-mortem-розбір розвʼязують різні задачі. Inspector і UI mode працюють там, де падіння відтворюється; трейс — єдиний спосіб розібрати те, що падає лише в CI, і читається без відтворення.
    • Трейс — це слід, а не кадр: дії з локаторами й тривалістю, DOM-знімки, мережа, консоль, метадані оточення. Тому дока радить його замість відео й скріншотів для CI-падінь — і не радить вмикати на кожен тест.
    • Артефакт існує лише тоді, коли його вивантажено: прогін живе на свіжій віртуальній машині, а шардований прогін дає один звіт лише після злиття blob-звітів.
    • Звіт — не лог і не «у нас Allure». Канон вимагає результатів, даних про систему й оточення в придатній для аудиторії формі, а тренди — історії прогонів, звʼязаної за ідентифікаторами тестів.

    Можливі питання

    • «Тест падає в CI, локально проходить — що робиш?» — очікують не «перезапущу», а метод: трейс на ретраї, артефакт, дія й локатор, мережа й метадані оточення. Інтервʼюер дивиться, чи є в тебе процедура, а не інтуїція.
    • «Що таке trace viewer і що в трейсі є?» — сильна відповідь називає склад (дії з локаторами й часом, DOM-знімки, мережу, консоль, метадані, вкладення) і головну властивість: це розбір після факту, без відтворення.
    • «Чому не писати трейс завжди?» — чекають аргумент вартості й знання штатної стратегії on-first-retry; додатковий плюс — наслідок «без ретраїв трейсу не буде».
    • «Чим UI mode відрізняється від debug mode?» — розводять живий покроковий розбір з логом придатності і режим із time travel, watch-режимом та автоматичним трейсуванням; згадка про пастку зі setup-тестами показує реальний досвід.
    • «Які репортери використовуєш і навіщо кілька?» — перевіряють, чи розумієш різні аудиторії: людський вивід у термінал, HTML для перегляду, JUnit XML як формат обміну для CI, blob для злиття шардів.
    • «Як зрозуміти, це баг продукту чи баг тесту?» — сильна відповідь дає ознаки: збіг фактичного й очікуваного при червоному тесті вказує на дефект автоматизації, масове падіння — на оточення, а flaky — на недетермінованість тесту або даних. Додатковий плюс — згадка трейсу й кореляційного ID як доказів у баг-репорті.

    Джерела

    Два режими: наживо і після факту

    • Playwright — Debugging Tests--debug як зміна конфігурації (видимий браузер, нульовий таймаут), page.pause(), склад логів придатності, PWDEBUG=console, поведінка розширення VS Code.
    • Playwright — Trace viewer — трейс як post-mortem-розбір «after the script has run», призначений для падінь у CI.
    • Playwright — Auto-waiting (actionability) — перелік перевірок придатності, які інспектор виводить у лог.

    UI mode: time travel і watch-режим

    • Playwright — UI Modetime travel і watch-режим, склад вкладок, розділення логів браузера й тесту, обмеження щодо setup-тестів.
    • Playwright — Trace viewer--trace on у режимі розробки й автоматичне трейсування кожного тесту в UI mode.

    Що лежить у трейсі

    • Playwright — Trace viewer — склад трейсу: дії з локаторами й тривалістю, DOM-знімки, помилки й таймлайн, мережа, метадані, вкладення з дифами; трейс не передає даних назовні.
    • Playwright — Debugging Tests — трейс як DOM-знімок кожної дії плюс час, параметри, значення, лог, консоль, мережа й вихідний код.
    • ISTQB® Certified Tester Advanced Level Test Automation Engineering (CTAL-TAE) v2.0 — §4.2, §6.1.1: перелік джерел даних для аналізу, скріншоти для аналізу першопричини, вимога зберігати при падінні все потрібне для аналізу.

    Стратегії запису: чому не «трейс завжди»

    Репортери: людині, машині і CI

    • Playwright — Reporters — кілька репортерів одночасно, різні набори локально й у CI, призначення list/line/dot/html/json/junit/blob, JUnit XML як формат обміну.
    • Playwright — Sharding — злиття blob-звітів в одній теці й номер шарда в імені файла.
    • Allure Report — History and retries — історія проти ретраїв, звʼязування прогонів за унікальним ідентифікатором тесту, копіювання теки history в теку результатів у Allure 2.
    • Allure Report — CategoriesProduct errors проти Test errors, одна категорія на результат, порядок кастомних правил.
    • ISTQB® Certified Tester Advanced Level Test Automation Engineering (CTAL-TAE) v2.0 — §6.1.1, §6.1.3: логи не дають огляду, обовʼязковий склад звіту про прогрес, публікація стейкхолдерам, залежність деталізації від аудиторії, тренди з попередніх прогонів.

    Розбір фейлу в CI: від репорту до першопричини

    • GitHub Docs — Understanding GitHub Actions — свіжа щойно розгорнута віртуальна машина на кожен прогін, власний ранер чи контейнер на кожну джобу, обмін даними між кроками однієї джоби.
    • Playwright — Trace viewer — трейс як інструмент розбору падінь CI: дії з локаторами, помилки з таймлайном, мережа, метадані оточення.
    • Playwright — Test retriesflaky як окремий стан «упав, але пройшов на ретраї».
    • Playwright — Continuous IntegrationDEBUG=pw:browser для помилок запуску браузера, headless за замовчуванням, Xvfb для видимого режиму на Linux-агентах.
    • ISTQB® Certified Tester Advanced Level Test Automation Engineering (CTAL-TAE) v2.0 — §6.1.1–6.1.3: процедура розбору падіння, збіг фактичного й очікуваного як ознака дефекту рішення автоматизації, масове падіння як симптом недоступного оточення, кореляційний ID, історія звітів для трендів.
    • Jest — Setup and Teardown — порада перевіряти передусім, чи падає тест, коли він єдиний у прогоні.
    • xUnit Test Patterns — Erratic Test — той самий клас нестабільності: тести, що взаємодіють між собою.

    Типові помилки

    Підсумок

    Можливі питання

    Пояснення

    «Поясни» працює з власним API-ключем Anthropic: запит іде з вашого браузера прямо до Anthropic.

    Свій API-ключ (BYOK)

    Вставте власний ключ Anthropic — пояснення працюватиме на реальній моделі. Ключ зберігається лише у вашому браузері (localStorage), нікуди не надсилається, крім api.anthropic.com, і не логується.