Розділ 1 з 12
Навіщо звіти і як вони працюють
Прогін тестів — це потік подій: прогін почався, тест стартував, крок завершився, тест упав, прогін закінчився. Репортер — це об'єкт, який отримує ці події і перетворює їх на щось корисне для конкретного читача.
Різним людям потрібні різні звіти. Розробнику під час роботи досить рядка в терміналі: що пройшло, що впало і де. CI-системі потрібен формат, який вона вміє показати на вкладці з тестами, наприклад JUnit XML. Тому, хто розбирає падіння, потрібен інтерактивний звіт зі скриншотами й трейсом. А для власної аналітики потрібні сирі дані в JSON. Playwright Test має набір вбудованих репортерів під ці задачі й дозволяє написати свій.
Усі репортери отримують ті самі події від раннера, тому їх можна вмикати одночасно: один пише в термінал, другий будує HTML, третій зберігає XML для CI. Репортер нічого не змінює у виконанні тестів, він лише спостерігає.
Розділ 2 з 12
Підключення репортерів
Репортер задається в конфігу, у командному рядку або через змінні оточення. Якщо його не задано, раннер обирає сам: list локально і dot у CI.
У конфігу опція reporter приймає або рядок з назвою, або масив кортежів «назва + об'єкт опцій». Масив дозволяє ввімкнути кілька репортерів одночасно. Поширений патерн — різні репортери для CI і локальної роботи через process.env.CI.
Для одного запуску репортер можна задати прапорцем. --reporter замінює репортери з конфігу, кілька назв перелічуються через кому. --add-reporter додає репортер поверх тих, що вже є в конфігу. Багато опцій вбудованих репортерів дублюються змінними оточення з префіксом PLAYWRIGHT_, наприклад PLAYWRIGHT_HTML_OPEN або PLAYWRIGHT_JSON_OUTPUT_NAME. Це зручно, коли конфіг міняти не можна.
Розділ 3 з 12
Термінальні репортери: list, line, dot
Три репортери пишуть у термінал і відрізняються лише детальністю. Порівняйте їх на одному й тому самому прогоні.
list друкує рядок на кожен запуск тесту з позначкою результату й тривалістю. Опція printSteps: true додає рядки для кроків test.step. line тримає один рядок прогресу, який постійно оновлюється, і друкує деталі лише тоді, коли тест остаточно впав. Тому його вивід компактний навіть для тисяч тестів. dot друкує один символ на результат і підходить для CI-логів, де важливий лише загальний підсумок. Значення символів взято з вихідного коду репортера: · — пройшов, F — упав, T — тайм-аут, ± — flaky, ° — пропущено, × — упав, але буде повтор.
Усі три після прогону друкують однаковий підсумок: деталі падінь, кількість тестів за статусами й загальний час. Опція omitTags прибирає теги з назв тестів у виводі.
Розділ 4 з 12
HTML reporter
HTML-звіт — головний інструмент розбору результатів. Це самодостатній вебзастосунок у каталозі playwright-report, з фільтрами, деталями кожного тесту, вкладеннями і вбудованим переглядом трейсів.
Звіт можна відфільтрувати за браузером і статусом: passed, failed, flaky, skipped. Клік на тест відкриває його помилки з фрагментом коду, кроки з тривалістю, вкладення (скриншоти, відео, трейси) і анотації. У Playwright 1.63 біля кроків з'явилася діаграма тривалості, тож видно, який крок «з'їв» найбільше часу.
Опції
open визначає, коли відкривати звіт після прогону: 'always', 'never' або 'on-failure'. Останнє значення діє за замовчуванням: звіт відкривається сам, лише якщо щось упало. У CI ставте 'never', інакше процес чекатиме, поки хтось закриє звіт. outputFolder змінює каталог звіту, за замовчуванням playwright-report. host і port визначають, де піднімається сервер для перегляду. title задає заголовок звіту. noSnippets прибирає фрагменти коду біля помилок. attachmentsBaseURL потрібен, коли вкладення лежать на окремому сервері.
Чому не відкривати index.html подвійним кліком
Проблема. Звіт відкривають прямо з файлової системи, і частина вмісту, зокрема трейси, не працює.
Чому. Звіт розрахований на роботу через HTTP-сервер. Команда show-report піднімає такий сервер локально.
Рішення. Відкривайте звіт через npx playwright show-report, а в CI публікуйте каталог як артефакт або статичний сайт.
Коли. Завжди, коли звіт потрапляє на іншу машину: з CI-артефакту, з архіву колеги.
Розділ 5 з 12
Машиночитані звіти: JSON, JUnit, GitHub
Ці репортери пишуть не для людини, а для інших інструментів: CI-системи, дашборду чи власного скрипта аналітики.
JSON-репортер формує один об'єкт з усією інформацією про прогін: конфіг, дерево файлів і тестів, результати кожної спроби зі статусами, помилками й вкладеннями, загальну статистику. JUnit-репортер пише XML у форматі, який розуміють Jenkins, GitLab, Azure DevOps та інші CI-системи. Вони показують тести на окремій вкладці.
Якщо файл не вказано, обидва репортери друкують результат у стандартний вивід. Майже завжди потрібен файл: його задає опція outputFile або змінна PLAYWRIGHT_JSON_OUTPUT_NAME / PLAYWRIGHT_JUNIT_OUTPUT_NAME. Відносний шлях рахується від каталогу конфігу.
Опції JUnit корисно знати поіменно. includeProjectInTestName додає назву проєкту до назви тесту, щоб у CI розрізняти той самий тест у різних браузерах. includeRetries включає в XML інформацію про повтори. stripANSIControlSequences прибирає з тексту помилок керівні символи кольорів терміналу.
Репортер github працює в GitHub Actions: він додає до коміту чи pull request анотації з падіннями прямо біля рядків коду. Документація радить вмикати його в CI замість dot: reporter: process.env.CI ? 'github' : 'list'.
Читаємо JSON власним скриптом
Приклад нижче рахує тести за статусом з файлу JSON-звіту. Тип JSONReport експортує сам Playwright, тож структуру звіту не треба описувати вручну.
Розділ 6 з 12
Blob, merge-reports і perfetto
Коли тести шардуються на кілька машин, кожна бачить лише свою частину. Blob-репортер зберігає «сирі» результати шарду, а merge-reports збирає з них один звичайний звіт.
Blob-звіт містить усі деталі прогону й вкладення, але не призначений для читання. За замовчуванням він пишеться в каталог blob-report. Після того як усі шарди відпрацювали, їхні blob-файли збирають в один каталог і запускають npx playwright merge-reports з потрібним репортером. Результат такий самий, наче всі тести йшли на одній машині.
У CI крок злиття зазвичай окрема задача, яка завантажує артефакти всіх шардів. Документація показує повний приклад workflow для GitHub Actions.
perfetto
Новий у Playwright 1.63 репортер perfetto пише файл у форматі Trace Event Format, за замовчуванням test-results/perfetto.json. Його відкривають у Perfetto UI або на сторінці chrome://tracing і бачать прогін як часову шкалу з окремою доріжкою для кожного воркера. Це зручно, щоб знайти, де воркери простоюють і які файли тягнуть прогін.
Розділ 7 з 12
Статуси і результати
У звітах живуть два різні поняття: статус окремої спроби тесту і підсумок тесту з урахуванням усіх спроб та очікувань. Їх плутають частіше за все інше.
Кожна спроба має статус: passed, failed, timedOut, skipped або interrupted. Останній означає, що спробу перервано ззовні: прогін зупинено через --max-failures чи вручну. Тест (TestCase) має очікуваний статус expectedStatus: зазвичай passed, а для test.fail() — failed. З порівняння спроб з очікуванням виходить підсумок outcome(): expected (усе як очікувалося), unexpected (не збіглося на жодній спробі), flaky (не збіглося, а на повторі збіглося) або skipped.
Саме outcome рахують підсумкові рядки «passed / failed / flaky» у терміналі та розділ stats у JSON. Звідси неочевидний наслідок: тест з test.fail(), який справді впав, рахується як очікуваний результат.
Статус у хуку afterEach
Під час виконання той самий статус доступний через testInfo. У afterEach він уже відомий, тож можна, наприклад, зібрати додаткову діагностику лише для тестів, що пішли не за планом. Порівнювати варто з testInfo.expectedStatus, а не з рядком 'failed': так коректно обробляються тести з test.fail().
Розділ 8 з 12
Вкладення, кроки й анотації
Звіт показує те, що тест йому дав. Чим краще тест структурований і чим більше контексту він прикріплює, тим швидше розбирається падіння.
Кроки
test.step ділить тест на іменовані кроки, і у звіті замість довгого списку кліків видно зрозумілу структуру. Кроки можна вкладати один в один. Опція box: true робить крок «коробкою»: якщо всередині щось упаде, помилка вказуватиме на виклик кроку, а не на рядок усередині хелпера. Це зручно для кроків з Page Object.
Вкладення
testInfo.attach() прикріплює до тесту довільні дані: текст, JSON, зображення або файл з диска. Вкладення з'являються в HTML-звіті біля тесту і передаються репортерам у result.attachments. Дані передаються або як body з contentType, або як path до файлу. Метод асинхронний, тож потрібен await.
Автоматичні артефакти
Скриншоти, відео й трейси раннер може прикріплювати сам. Їх вмикають у use: screenshot, video, trace. Документація радить для CI режими, що зберігають артефакти лише при проблемах: вони дають діагностику без великих витрат часу й місця.
Анотації і теги
Анотації (annotation: { type, description }) і теги (tag: '@smoke') відображаються в HTML-звіті, а репортерам доступні через test.annotations і test.tags. Анотацію типу issue з посиланням на задачу зручно додавати до відомих багів.
Розділ 9 з 12
Трейси і Trace Viewer
Трейс — найдетальніше вкладення: повний запис спроби тесту, який можна прокрутити крок за кроком уже після прогону.
Trace Viewer показує список дій з тривалістю, знімки DOM до, під час і після кожної дії, мережеві запити, консоль браузера, помилки, вихідний код тесту й метадані. Знімки інтерактивні: можна інспектувати елементи й перевіряти локатори просто в записі. Відкрити трейс можна трьома способами: з HTML-звіту (кнопка біля тесту), командою npx playwright show-trace або завантаживши файл на trace.playwright.dev. Останній варіант обробляє трейс у браузері й нікуди його не надсилає.
Трейси бувають великими. Режим 'on' записує кожну спробу кожного тесту. Для CI документація радить 'on-first-retry' або 'retain-on-failure': так діагностика є саме там, де вона потрібна.
Розділ 10 з 12
Власний reporter
Коли вбудованих форматів замало, наприклад потрібно надіслати підсумок у месенджер чи записати метрики у власну систему, пишуть свій репортер. Це клас з методами, які раннер викликає на кожну подію.
Усі методи інтерфейсу Reporter необов'язкові: реалізуйте лише ті події, що потрібні. Типи імпортуються з @playwright/test/reporter. onBegin отримує конфіг і кореневий Suite з усіма зібраними тестами. onTestBegin і onTestEnd викликаються для кожної спроби. onStepBegin і onStepEnd — для кроків. onError — для глобальних помилок поза тестами. onEnd — після прогону, з підсумковим статусом; він може бути асинхронним, і саме тут зазвичай пишуть файли чи надсилають запити. onExit — останній шанс прибрати за собою. Метод printsToStdio() варто повертати false, якщо репортер не пише в термінал: тоді раннер сам додасть стандартний вивід, щоб людина бачила прогрес.
Шлях до власного репортера вказується відносно конфігу, а об'єкт опцій з кортежу потрапляє в конструктор. Тримайте репортери в окремому каталозі на кшталт reporters/, а не серед тестів, щоб раннер не намагався зібрати їх як тестові файли.
Розділ 11 з 12
Типові помилки
Більшість проблем зі звітами — не баги, а неправильні налаштування: звіт не туди пишеться, не тоді відкривається або його ніхто не бачить.
Найчастіше трапляються такі помилки. HTML-звіт у CI з open за замовчуванням або 'always'. JSON чи JUnit без файлу, коли результат змішується з виводом у консолі. --reporter замість --add-reporter, через що зникають репортери з конфігу. Шардовані прогони без blob і злиття. trace: 'on-first-retry' без повторів. testInfo.attach без await. Порівняння статусу з 'failed' замість expectedStatus. І власний репортер, що не пише в термінал, але повертає true з printsToStdio.
Розділ 12 з 12
Шпаргалка
Усе основне на одному екрані. Після шпаргалки — підсумковий квіз для самоперевірки.
Три правила на пам'ять. Кожен репортер має свого читача, і їх можна поєднувати. У CI звіт не відкривається сам, а зберігається як артефакт. Діагностику (трейси, скриншоти, відео) вмикають у режимах «лише при проблемах», щоб вона була там, де потрібна, і не гальмувала решту.
Самоперевірка
Підсумковий квіз
15 питань за всіма розділами. Після кожної відповіді побачите пояснення, а в кінці — список тем, які варто повторити.