QA Interview Hub · База знань · Тести
Playwright
Дебаг, trace viewer, звіти, flaky
Діагностика: trace viewer, репорти, flaky-тести
Trace viewer — головний інструмент дебагу: у трейсі записані кожна дія, DOM-знімки до й після, мережа, консоль і вихідний код тесту. У CI зазвичай ставлять trace: 'on-first-retry', щоб не витрачати ресурси на успішні прогони. Відкривають трейс через npx playwright show-trace або з HTML-звіту.
Локально для дебагу є UI mode (--ui) з time-travel, режим --debug з Playwright Inspector і page.pause(). Codegen (npx playwright codegen) записує дії та підказує локатори. Звіти: вбудований HTML, list, JUnit для CI, а також Allure.
Для пошуку flaky використовують --repeat-each=10 і --retries, а в HTML-звіті такі тести позначаються як flaky. Типові причини: спільні дані між воркерами, відсутність web-first assertions, waitForTimeout, анімації, повільне CI-середовище. Лікують першопричину — ретраї лише маскують проблему.
Локальний дебаг: інструменти і коли який
npx playwright test --ui — UI mode. Список тестів, watch-режим (перезапуск при зміні файлу), time-travel по кроках з DOM-знімками, мережею і консоллю. Мій основний інструмент при написанні тестів.--debug або змінна PWDEBUG=1 — Playwright Inspector: покрокове виконання, браузер у headed-режимі, таймаути вимкнені. Зручно, щоб зупинитися перед конкретною дією.await page.pause() — точка зупинки в коді, відкриває Inspector саме тут.--headed і launchOptions: { slowMo: 300 } — побачити, що відбувається, у сповільненому темпі.- Розширення для VS Code — запуск окремого тесту, breakpoints, кнопка Pick locator, яка показує рекомендований локатор для елемента.
Codegen корисніший, ніж здається, не лише для запису дій:
npx playwright codegen --device="iPhone 13" --lang=uk-UA https://app.test
npx playwright codegen --save-storage=auth.json https://app.test/login
npx playwright codegen --load-storage=auth.json https://app.test/dashboard
Перша команда відкриває застосунок з емуляцією пристрою, друга зберігає стан після ручного логіну, третя відкриває вже залогіненим. Згенерований код я не комічу як є: беру з нього локатори, а структуру переписую під Page Object і фікстури.
Для дебагу в CI цей набір не працює, там основне — trace.
На співбесіді: Під час написання тестів я працюю в UI mode з watch-режимом, для зупинки на конкретному кроці використовую page.pause() або --debug. Codegen беру для швидкого підбору локаторів і збереження стану логіну, але код після нього переписую.
Артефакти і звіти
Що записувати, налаштовується в use:
| Опція | Корисні значення |
|---|
| trace | on-first-retry, retain-on-failure, on |
| screenshot | only-on-failure, on |
| video | retain-on-failure, on-first-retry |
on-first-retry пише артефакт лише при першому ретраї, тому без retries він нічого не дасть. retain-on-failure пише завжди, але зберігає лише для тестів, що впали — це дорожче за ресурсами, зате артефакт є навіть без ретраїв.
Можна одночасно кілька репортерів:
reporter: process.env.CI
? [['blob'], ['junit', { outputFile: 'results/junit.xml' }], ['github']]
: [['html', { open: 'on-failure' }], ['list']],
github додає анотації помилок прямо в PR, JUnit читає Jenkins чи GitLab, HTML — для людей. Для Allure підключають allure-playwright.
Власні дані до звіту додають через testInfo.attach:
test('звірка виписки', async ({ request }, testInfo) => {
const res = await request.get('/api/statement');
await testInfo.attach('statement', {
body: await res.text(),
contentType: 'application/json',
});
});
Так у звіті з'являються відповіді API, логи бекенду, згенеровані файли. Коли тест падає, розробник бачить не лише скріншот, а й дані, з якими працював тест.
На співбесіді: У CI я ставлю trace: 'on-first-retry' разом з ретраями, скріншоти лише при падінні, і кілька репортерів: blob для шардів, JUnit для CI і github для анотацій у PR. Додаткові дані, як відповіді API, прикріплюю через testInfo.attach.
Як я системно розбираю flaky-тест
Флакі-тест — це не «просто перезапусти». Мій процес:
- Відтворити.
npx playwright test checkout.spec.ts --repeat-each=20. Якщо падає локально — добре, є що дебажити. - Перевірити ізоляцію. Запустити з
--workers=1 і окремо з --workers=4. Якщо падає лише паралельно — проблема в спільних даних або акаунті між воркерами. - Перевірити порядок. Запустити тест окремо через
-g "назва". Якщо окремо проходить, а в наборі падає — від нього залежить інший тест або залишки даних. - Порівняти trace успішного і неуспішного прогону. Часто видно, що на падінні API відповів повільніше, або спінер ще перекривав кнопку.
- Класифікувати причину: тест (немає очікування, крихкий локатор), дані, середовище, чи справжній баг застосунку, наприклад race condition у фронтенді.
Останній пункт важливий: частина флакі — це реальні баги, які користувач теж зустріне. Якщо подвійний клік створює два платежі, це не проблема тесту.
Поки причина не виправлена, тест не має блокувати команду. Я позначаю його test.fixme з посиланням на тікет або виношу в карантинний проєкт з тегом @quarantine, який не блокує мерж. Але в карантину має бути власник і строк, інакше він перетворюється на смітник.
Метрика, яку варто відстежувати, — частка флакі-тестів у прогонах. HTML-звіт позначає тест як flaky, якщо він пройшов лише після ретраю.
На співбесіді: Я відтворюю флакі через --repeat-each, перевіряю ізоляцію зміною кількості воркерів і порівнюю trace успішного й неуспішного прогону. Потім класифікую причину, бо частина флакі — це реальні race condition в застосунку. До виправлення тест іде в карантин з тікетом і власником.