Playwrightで作成できるレポートを調べてみました。公式ドキュメントはPlaywright Test Reportersです。結論をいうと、簡単にファイル出力するだけならAllureが一番よかったです。
Listレポーター
シンプルな箇条書き形式。
npx playwright test ./tests/sample.spec.ts --reporter=list
Running 3 tests using 3 workers
✘ 1 [Google Chrome] › sample.spec.ts:27:5 › faied test (30.0s)
✓ 2 [Google Chrome] › sample.spec.ts:14:5 › get agile link (592ms)
✓ 3 [Google Chrome] › sample.spec.ts:5:5 › has title (470ms)
1) [Google Chrome] › sample.spec.ts:27:5 › faied test ────────────────────────────────────────────
Test timeout of 30000ms exceeded.
Error: locator.click: Test timeout of 30000ms exceeded.
Call log:
- waiting for locator('a').filter({ hasText: /^Non-existent element$/ })
31 |
32 | // クリックできないところをクリック
> 33 | await page.locator('a', { hasText: /^Non-existent element$/, timeout: 1000 }).click();
| ^
34 | });
35 |
at /Users/daipresents/Work/playwright/tests/sample.spec.ts:33:66
1 failed
[Google Chrome] › sample.spec.ts:27:5 › faied test ─────────────────────────────────────────────
2 passed (30.6s)
以下のように設定すれば、ステップを設定してそれごとに出力もできる。
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [['list', { printSteps: true }]],
});
Lineレポーター
Listよりシンプル。
npx playwright test ./tests/sample.spec.ts --reporter=line
Running 3 tests using 3 workers
1) [Google Chrome] › sample.spec.ts:27:5 › faied test ────────────────────────────────────────────
Test timeout of 30000ms exceeded.
Error: locator.click: Test timeout of 30000ms exceeded.
Call log:
- waiting for locator('a').filter({ hasText: /^Non-existent element$/ })
31 |
32 | // クリックできないところをクリック
> 33 | await page.locator('a', { hasText: /^Non-existent element$/ }).click();
| ^
34 | });
35 |
at /Users/daipresents/Work/playwright/tests/sample.spec.ts:33:66
1 failed
[Google Chrome] › sample.spec.ts:27:5 › faied test ─────────────────────────────────────────────
2 passed (30.5s)
Dotレポーター
あんまり便利に思ったことはないけど、わかりやすいっちゃわかりやすい。
npx playwright test ./tests/sample.spec.ts --reporter=dot
Running 3 tests using 3 workers
··T
1) [Google Chrome] › sample.spec.ts:27:5 › faied test ────────────────────────────────────────────
Test timeout of 30000ms exceeded.
Error: locator.click: Test timeout of 30000ms exceeded.
Call log:
- waiting for locator('a').filter({ hasText: /^Non-existent element$/ })
31 |
32 | // クリックできないところをクリック
> 33 | await page.locator('a', { hasText: /^Non-existent element$/ }).click();
| ^
34 | });
35 |
at /Users/daipresents/Work/playwright/tests/sample.spec.ts:33:66
1 failed
[Google Chrome] › sample.spec.ts:27:5 › faied test ─────────────────────────────────────────────
2 passed (30.6s)
HTMLレポーター
基本これで十分デバッグできるけど、後に紹介するサードパーティーツールやサービスを使ったほうがきれいなレポートになる。
npx playwright test ./tests/sample.spec.ts --reporter=html
Running 3 tests using 3 workers
1) [Google Chrome] › sample.spec.ts:27:5 › faied test ────────────────────────────────────────────
Test timeout of 30000ms exceeded.
Error: locator.click: Test timeout of 30000ms exceeded.
Call log:
- waiting for locator('a').filter({ hasText: /^Non-existent element$/ })
31 |
32 | // クリックできないところをクリック
> 33 | await page.locator('a', { hasText: /^Non-existent element$/ }).click();
| ^
34 | });
35 |
at /Users/daipresents/Work/playwright/tests/sample.spec.ts:33:66
1 failed
[Google Chrome] › sample.spec.ts:27:5 › faied test ─────────────────────────────────────────────
2 passed (30.6s)
Serving HTML report at http://localhost:9323. Press Ctrl+C to quit.
レポートを開くときはnpx playwright show-report
を叩く。
BLOBレポーター
コンソールの出力は特に変化なし。ただし、テストに関係する情報(Chromeなどが取得しているネットワーク情報など)を集めたBLOBファイルをZip形式で出力してくれる(場所:blob-report/report.zip
)。レポートとしてみるというより、このデータを材料として使って別ツールやサービスでレポートを作るイメージ。
npx playwright test ./tests/sample.spec.ts --reporter=blob
Running 3 tests using 3 workers
1) [Google Chrome] › sample.spec.ts:27:5 › faied test ────────────────────────────────────────────
Test timeout of 30000ms exceeded.
Error: locator.click: Test timeout of 30000ms exceeded.
Call log:
- waiting for locator('a').filter({ hasText: /^Non-existent element$/ })
31 |
32 | // クリックできないところをクリック
> 33 | await page.locator('a', { hasText: /^Non-existent element$/ }).click();
| ^
34 | });
35 |
at /Users/daipresents/Work/playwright/tests/sample.spec.ts:33:66
1 failed
[Google Chrome] › sample.spec.ts:27:5 › faied test ─────────────────────────────────────────────
2 passed (30.6s)
JSONレポーター
これも結果データを加工したいときに使えそう。
npx playwright test ./tests/sample.spec.ts --reporter=json
{
"config": {
"configFile": "/Users/daipresents/Work/playwright/playwright.config.ts",
"rootDir": "/Users/daipresents/Work/playwright/tests",
"forbidOnly": false,
"fullyParallel": true,
"globalSetup": null,
"globalTeardown": null,
"globalTimeout": 0,
"grep": {},
"grepInvert": null,
"maxFailures": 0,
"metadata": {
"actualWorkers": 3
},
"preserveOutput": "always",
"reporter": [
[
"json"
]
],
"reportSlowTests": {
"max": 5,
"threshold": 15000
},
"quiet": false,
"projects": [
{
"outputDir": "/Users/daipresents/Work/playwright/test-results",
"repeatEach": 1,
"retries": 0,
"id": "Google Chrome",
"name": "Google Chrome",
"testDir": "/Users/daipresents/Work/playwright/tests",
"testIgnore": [],
"testMatch": [
"**/*.@(spec|test).?(c|m)[jt]s?(x)"
],
"timeout": 30000
}
],
"shard": null,
"updateSnapshots": "missing",
"version": "1.41.1",
"workers": 5,
"webServer": null
},
"suites": [
{
"title": "sample.spec.ts",
"file": "sample.spec.ts",
"column": 0,
"line": 0,
"specs": [
{
"title": "has title",
"ok": true,
"tags": [],
"tests": [
{
"timeout": 30000,
"annotations": [],
"expectedStatus": "passed",
"projectId": "Google Chrome",
"projectName": "Google Chrome",
"results": [
{
"workerIndex": 0,
"status": "passed",
"duration": 463,
"errors": [],
"stdout": [],
"stderr": [],
"retry": 0,
"startTime": "2024-02-21T07:50:52.556Z",
"attachments": []
}
],
"status": "expected"
}
],
"id": "b92766bcf73bd5c029a8-aceec34c6ede2bf0c566",
"file": "sample.spec.ts",
"line": 5,
"column": 5
},
{
"title": "get agile link",
"ok": true,
"tags": [],
"tests": [
{
"timeout": 30000,
"annotations": [],
"expectedStatus": "passed",
"projectId": "Google Chrome",
"projectName": "Google Chrome",
"results": [
{
"workerIndex": 1,
"status": "passed",
"duration": 587,
"errors": [],
"stdout": [],
"stderr": [],
"retry": 0,
"startTime": "2024-02-21T07:50:52.556Z",
"attachments": []
}
],
"status": "expected"
}
],
"id": "b92766bcf73bd5c029a8-d15b4972ea9764541107",
"file": "sample.spec.ts",
"line": 14,
"column": 5
},
{
"title": "faied test",
"ok": false,
"tags": [],
"tests": [
{
"timeout": 30000,
"annotations": [],
"expectedStatus": "passed",
"projectId": "Google Chrome",
"projectName": "Google Chrome",
"results": [
{
"workerIndex": 2,
"status": "timedOut",
"duration": 30000,
"error": {
"message": "\u001b[31mTest timeout of 30000ms exceeded.\u001b[39m"
},
"errors": [
{
"message": "\u001b[31mTest timeout of 30000ms exceeded.\u001b[39m"
},
{
"location": {
"file": "/Users/daipresents/Work/playwright/tests/sample.spec.ts",
"column": 66,
"line": 33
},
"message": "Error: locator.click: Test timeout of 30000ms exceeded.\nCall log:\n \u001b[2m- waiting for locator('a').filter({ hasText: /^Non-existent element$/ })\u001b[22m\n\n\n\u001b[0m \u001b[90m 31 |\u001b[39m\u001b[0m\n\u001b[0m \u001b[90m 32 |\u001b[39m \u001b[90m// クリックできないところをクリック\u001b[39m\u001b[0m\n\u001b[0m\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 33 |\u001b[39m \u001b[36mawait\u001b[39m page\u001b[33m.\u001b[39mlocator(\u001b[32m'a'\u001b[39m\u001b[33m,\u001b[39m { hasText\u001b[33m:\u001b[39m \u001b[35m/^Non-existent element$/\u001b[39m })\u001b[33m.\u001b[39mclick()\u001b[33m;\u001b[39m\u001b[0m\n\u001b[0m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\u001b[0m\n\u001b[0m \u001b[90m 34 |\u001b[39m })\u001b[33m;\u001b[39m\u001b[0m\n\u001b[0m \u001b[90m 35 |\u001b[39m\u001b[0m\n\n\u001b[2m at /Users/daipresents/Work/playwright/tests/sample.spec.ts:33:66\u001b[22m"
}
],
"stdout": [],
"stderr": [],
"retry": 0,
"startTime": "2024-02-21T07:50:52.556Z",
"attachments": []
}
],
"status": "unexpected"
}
],
"id": "b92766bcf73bd5c029a8-c164d0bddc9f214bc244",
"file": "sample.spec.ts",
"line": 27,
"column": 5
}
]
}
],
"errors": [],
"stats": {
"startTime": "2024-02-21T07:50:52.330Z",
"duration": 30590.01,
"expected": 2,
"skipped": 0,
"unexpected": 1,
"flaky": 0
}
}
JUnitレポーター
JUnitで使われるXML形式はJenkinsなど様々な場所で活用できるフォーマット。
npx playwright test ./tests/sample.spec.ts --reporter=junit
<testsuites id="" name="" tests="3" failures="1" skipped="0" errors="0" time="30.754874">
<testsuite name="sample.spec.ts" timestamp="2024-02-21T11:48:21.690Z" hostname="Google Chrome" tests="3" failures="1" skipped="0" time="32.084" errors="0">
<testcase name="has title" classname="sample.spec.ts" time="0.512">
</testcase>
<testcase name="get agile link" classname="sample.spec.ts" time="1.572">
</testcase>
<testcase name="faied test" classname="sample.spec.ts" time="30">
<failure message="sample.spec.ts:29:5 faied test" type="FAILURE">
<![CDATA[ [Google Chrome] › sample.spec.ts:29:5 › faied test ───────────────────────────────────────────────
Test timeout of 30000ms exceeded.
Error: locator.click: Test timeout of 30000ms exceeded.
Call log:
- waiting for locator('a').filter({ hasText: /^Non-existent element$/ })
33 |
34 | // クリックできないところをクリック
> 35 | await page.locator('a', { hasText: /^Non-existent element$/ }).click();
| ^
36 | });
37 |
at /Users/daipresents/Work/playwright/tests/sample.spec.ts:35:66
attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
test-results/sample-faied-test-Google-Chrome/failure.png
────────────────────────────────────────────────────────────────────────────────────────────────
]]>
</failure>
<system-out>
<![CDATA[
[[ATTACHMENT|../test-results/sample-faied-test-Google-Chrome/failure.png]]
]]>
</system-out>
</testcase>
</testsuite>
</testsuites>
サードパーティーレポーター
Playwrightはサードパーティーツールを使ってレポート生成できる。
Allure
ダウンロード数を見る限り一番人気に見える。
- Link
インストール方法は以下。
# For Mac
brew install allure
# Windows is here: https://allurereport.org/docs/gettingstarted-installation/#install-via-scoop-for-windows
# Install package
npm i -D @playwright/test allure-playwright
実行してレポート生成して開く。 レポートはデフォルトallure-results
に生成される。
npx playwright test ./tests/sample.spec.ts --reporter=allure-playwright
allure generate ./allure-results --clean && allure open ./allure-report
Allureを使ってスクリーンショットを取る場合は以下のように書く。
import { allure } from "allure-playwright";
test('has title', async ({ page }) => {
...
// Take a screenshot
await allure.attachment("basic-page-screen", await page.screenshot(), {
contentType: "image/png",
});
...
});
レポートのイメージは以下。
Currents
レポーティングサービスなので調べず。
Monocart
Allureと比べると派手さがない。
インストールは以下のように簡単。
npm i -D monocart-reporter
以下のように実行してレポートを開く。
npx playwright test ./tests/sample.spec.ts --reporter=monocart-reporter
[MR] generating report data ...
[MR] generating test report ...
[MR] Test Report
┌─────────────┬────────────────────┐
│ Tests │ 3 │
│ ├ Passed │ 2 (66.7%) │
│ ├ Flaky │ 0 (0.0%) │
│ ├ Skipped │ 0 (0.0%) │
│ └ Failed │ 1 (33.3%) │
│ Steps │ 38 │
│ Suites │ 1 │
│ ├ Projects │ 1 │
│ ├ Files │ 1 │
│ ├ Describes │ 0 │
│ └ Shards │ 0 │
│ Retries │ 0 │
│ Errors │ 2 │
│ Logs │ 0 │
│ Attachments │ 0 │
│ Artifacts │ 0 │
│ Playwright │ v1.41.2 │
│ Date │ 2024/2/21 17:38:43 │
│ Duration │ 31.7s │
└─────────────┴────────────────────┘
[MR] html report: test-results/report.html (json: test-results/report.json)
[MR] view report: npx monocart show-report test-results/report.html
# Open the report.
npx monocart show-report test-results/report.html
レポートは以下のようになる。
ReportPortal
AIを使って解析してくれるサービス。Dockerでセルフホストできるらしいのでまたの機会に調べたい。
- Link
Serenty/JS
オープンソースの受け入れテストフレームワーク。
Testmo
テスト管理ツールサービスのレポーティング機能に繋げられるらしい。自動テストと手動テストの管理が便利そう。
Testomat.io
こちらもテスト管理サービス。
- Link:
Tesults
こちらもテスト管理サービス。管理サービスがレポーティング機能を提供する形が流行っている模様。
[…] ReportPortalは自動テスト結果の分析や、リアルタイムモニタリングを行うサービス。AIを活用したダッシュボードを簡単に作成できる。こういったレポート作成はPlaywrightだとAllureで十分だけど、作成したレポートをどこにホスティングするか設計する必要がある。その点、こういったダッシュボードサービスを使えば、パーマリンクが作成されるので、そのURLをみんなで共有すればいい。 […]
いいねいいね