今回やること
Playwrightは、ブラウザを自動操作して画面の動きを検証できるテストツールです。
この記事では、小さなTodo画面をローカルfixtureとして作り、次の操作を1本のテストにします。
- ラベルを使って入力欄を見つける
- Todoの文章を入力する
- ボタンを押す
- 一覧、完了メッセージ、入力欄の状態を確認する
- HTMLレポートとtraceで操作履歴を見る
fixtureは、テスト専用に用意する固定の画面やデータです。今回はHTMLをpage.setContent()でブラウザへ直接読み込むため、Webサーバーは起動しません。
この練習で確認するのは、fixture内のUIとブラウザ操作です。実際の配信経路、ネットワーク、バックエンド、データベースまでを通す本来のEnd-to-End検証ではありません。
使用環境
2026年7月25日時点で、npmのlatest安定版は@playwright/test@1.61.1です。AlphaやBeta版は使いません。
この記事ではPlaywrightが対応するブラウザのうち、Chromiumだけを導入します。
node --version
npm --version
Node.jsとnpmのバージョン番号が表示されることを確認してください。
1. プロジェクトを作る
mkdir playwright-fixture-practice
cd playwright-fixture-practice
npm init -y
npm pkg set type=module
npm pkg set "scripts.test=playwright test"
npm install --save-dev @playwright/test@1.61.1
npx playwright install chromium
mkdir -p fixture tests
Windows PowerShellでは、最後の行の代わりに次を実行します。
New-Item -ItemType Directory -Force fixture, tests
ChromiumはPlaywrightがテスト用に管理するブラウザです。普段使っているGoogle Chromeとは別にダウンロードされます。
2. ローカルfixture画面を作る
fixture/index.htmlを作ります。
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Todo Fixture</title>
<style>
body {
max-width: 40rem;
margin: 3rem auto;
padding: 0 1rem;
font-family: system-ui, sans-serif;
}
form {
display: grid;
gap: 0.75rem;
}
input,
button {
padding: 0.75rem;
font: inherit;
}
button {
cursor: pointer;
}
</style>
</head>
<body>
<main>
<h1>やることリスト</h1>
<form id="todo-form">
<label for="todo-title">やること</label>
<input id="todo-title" name="title" maxlength="100" required />
<button type="submit">追加</button>
</form>
<ul aria-label="やること一覧"></ul>
<p role="status" aria-live="polite"></p>
</main>
<script>
const form = document.querySelector("#todo-form");
const input = document.querySelector("#todo-title");
const list = document.querySelector('[aria-label="やること一覧"]');
const status = document.querySelector('[role="status"]');
form.addEventListener("submit", (event) => {
event.preventDefault();
const title = input.value.trim();
if (!title) {
status.textContent = "やることを入力してください";
return;
}
const item = document.createElement("li");
item.textContent = title;
list.append(item);
form.reset();
status.textContent = "1件追加しました";
});
</script>
</body>
</html>
labelのforと入力欄のidが一致しているため、利用者はラベルを押して入力欄へ移動でき、テストもgetByLabel()で要素を見つけられます。
role="status"とaria-live="polite"は、更新されたメッセージを支援技術へ伝えるための指定です。
3. Chromium 1つに設定する
プロジェクト直下にplaywright.config.tsを作ります。
import { defineConfig, devices } from "@playwright/test";
export default defineConfig({
testDir: "./tests",
reporter: [
["list"],
["html", { open: "never" }],
],
use: {
trace: "on",
},
projects: [
{
name: "chromium",
use: {
...devices["Desktop Chrome"],
browserName: "chromium",
},
},
],
});
projectsはChromiumの1件だけですhtmlreporterはplaywright-reportフォルダーへ結果を作りますtrace: "on"は操作、DOM snapshot、ネットワークなどを毎回記録します
traceを毎回残すと実行時間と保存容量が増えます。これは1テストだけの学習用設定です。大きなテスト群では、失敗時や再試行時だけ残す設定を検討します。
4. 利用者視点のテストを書く
tests/todo.spec.tsを作ります。
import { readFileSync } from "node:fs";
import { expect, test } from "@playwright/test";
const fixtureHtml = readFileSync(
new URL("../fixture/index.html", import.meta.url),
"utf8",
);
test("入力したTodoを一覧へ追加できる", async ({ page }) => {
await page.setContent(fixtureHtml);
const titleInput = page.getByLabel("やること");
await titleInput.fill("Playwrightを練習する");
await page.getByRole("button", { name: "追加" }).click();
await expect(page.getByRole("listitem")).toHaveText(
"Playwrightを練習する",
);
await expect(page.getByRole("status")).toHaveText("1件追加しました");
await expect(titleInput).toHaveValue("");
});
getByLabelとgetByRole
getByLabel("やること")は、画面上のラベルを手がかりに入力欄を探します。
getByRole("button", { name: "追加" })は、アクセシブルな役割と名前でボタンを探します。CSSクラスやHTMLの並び順より、利用者が認識する情報へ近いロケーターです。
web-first assertion
次の形はPlaywrightのweb-first assertionです。
await expect(page.getByRole("status")).toHaveText("1件追加しました");
画面が期待する状態になるまで、制限時間内で自動的に再確認します。要素を取得してすぐ文字列を比較するより、非同期に更新される画面で安定しやすい書き方です。
5. テストを実行する
npm test
次のように1件が成功すれば、Chromiumで入力、クリック、表示確認まで実行できています。
Running 1 test using 1 worker
✓ 1 [chromium] › todo.spec.ts:...
1 passed
テストはpage.setContent()でfixtureを読み込むため、別のターミナルで開発サーバーを起動する必要はありません。
6. HTMLレポートとtraceを見る
テスト後、HTMLレポートを開きます。
npx playwright show-report
レポートで「入力したTodoを一覧へ追加できる」を開き、次を確認します。
- Chromiumのテストが合格している
- 入力、クリック、3つのassertionが順番に並んでいる
- traceを開くリンクがある
traceを開くと、Actionsで操作順、Snapshotで各時点のDOMを確認できます。テストが失敗した時は、どの操作まで成功し、画面がどの状態だったかを追跡できます。
HTMLレポートやtraceには、テスト中の画面内容や通信情報が含まれる場合があります。実サービスで利用する時は、パスワード、トークン、個人情報をテストデータへ入れないでください。
成功確認
次の5点を確認できれば完了です。
- Chromiumだけがインストール・実行対象になっている
getByLabelで入力欄を操作しているgetByRoleでボタン、list item、statusを特定している- 3つのweb-first assertionが成功する
- HTMLレポートからtraceの操作履歴を確認できる
よくあるつまずき
Executable doesn't existと表示される
Playwright本体を入れても、ブラウザは別に導入する必要があります。
npx playwright install chromium
fixtureファイルが見つからない
次の構成になっているか確認します。
playwright-fixture-practice/
├── fixture/
│ └── index.html
├── tests/
│ └── todo.spec.ts
└── playwright.config.ts
テストファイルから見て../fixture/index.htmlにあることが重要です。
getByLabelが要素を見つけられない
HTMLのlabelとinputを確認します。
<label for="todo-title">やること</label>
<input id="todo-title" />
forとidは同じ値にします。
POSTやデータベースも検証できたと思ってしまう
今回のfixtureはブラウザ内のJavaScriptだけで動きます。ネットワークAPIやデータベースは存在しません。実アプリのE2Eでは、実際に配信されたURLへpage.goto()し、テスト用環境の境界を決める必要があります。
HTMLレポートが作られない
playwright.config.tsのreporterにhtmlがあるか確認し、設定ファイルがあるフォルダーでnpm testを実行してください。
練習
fixtureへ「完了」チェックボックスを追加する前に、今ある画面のテストを1つだけ強化します。
- Todoを追加した後、
getByRole("list")の要素数を確認する - もう1件追加する
toHaveCount(2)でlist itemが2件になったことを確認する
ロケーターは引き続きgetByRoleまたはgetByLabelを優先し、CSSクラスへ依存しないようにします。
次のステップ
次は、小さな実アプリをローカルサーバーで起動し、page.goto()でアクセスするテストへ進むと、配信経路を含むE2Eへ近づきます。
認証状態、Page Object Model、API mock、visual regression、複数ブラウザ、CIは、最初の1テストを安定して実行できてから、それぞれ別の学習ゴールとして追加してください。
参考リソース
- Playwright公式: Installation
- Playwright公式: Locators
- Playwright公式: Assertions
- Playwright公式: HTML Reporter
- Playwright公式: Trace Viewer
- npm: @playwright/test