Playwright は Microsoft 発の E2E テストフレームワークとして、Cypress / Selenium / Puppeteer のシェアを完全に塗り替えた存在です。3 ブラウザ(Chromium / Firefox / WebKit)を 1 API で・auto-waiting で Flaky なし・並列実行・シャーディング・ビデオ / スクリーンショット / トレース自動取得・Codegen / UI Mode / Trace Viewer という最強のデバッグツール——E2E テストが「遅くて壊れやすい」時代の常識を過去のものにしました。
2025〜2026 年に入ってさらに進化しました。Aria Snapshots(アクセシビリティツリー比較)、locator.describe() によるトレース可読性向上、expect().toContainClass()、IndexedDB 対応 storageState、Box Fixtures、Copy Prompt による LLM 連携、testProject.workers、Timeline in Speedboard、Codegen の toBeVisible 自動生成など、v1.49〜v1.58 で実戦用途の穴がほぼすべて埋まりました。
この記事では 2026 年 4 月時点の Playwright を前提に、E2E / コンポーネント / API テストの書き方、ユーザー視点ロケーターの優先順位、Web-first Assertions、Fixtures、storageState でのログイン共有、UI Mode・Trace Viewer・Codegen の使い方、Aria Snapshots と Visual Regression、Parallel 実行・Sharding、Page Object Model、GitHub Actions CI 統合、落とし穴までを実戦コードで網羅します。
- 2026 年 4 月時点のバージョン整理
- Playwright vs Cypress vs Selenium vs Puppeteer
- インストールと初期セットアップ
- Locator ── ユーザー視点での要素指定
- Web-first Assertions ── auto-waiting が効く expect
- テストの基本構造 ── test / describe / hooks
- storageState ── ログイン状態を全テストで共有
- Fixtures ── test.extend でカスタム依存性注入
- Page Object Model ── 巨大アプリでの保守性
- Codegen / UI Mode / Trace Viewer ── 三大ツール
- API テスト ── ブラウザを立ち上げずに REST を叩く
- コンポーネントテスト
- Aria Snapshots と Visual Regression
- 並列実行とシャーディング ── CI 時間を桁違いに短縮
- GitHub Actions での CI 統合
- 落とし穴と注意点
- よくある質問
- まとめ
2026 年 4 月時点のバージョン整理
| リリース | 時期 | 主なハイライト |
|---|---|---|
| Playwright 1.49 | 2024 年末 | Aria Snapshots(toMatchAriaSnapshot)導入。アクセシビリティツリー比較 |
| Playwright 1.51 | 2025 年 | IndexedDB 対応 storageState、Box Fixtures、Copy Prompt(LLM プロンプト生成) |
| Playwright 1.52 | 2025 年 | expect().toContainClass()、testProject.workers(プロジェクト単位の並列数) |
| Playwright 1.55 | 2025 年 | Codegen で toBeVisible アサーションを自動生成 |
| Playwright 1.57 | 2025 年 | locator.describe() でトレース / レポートに説明付与、UI Mode のシステムテーマ対応 |
| Playwright 1.58 | 2026 年 | HTML Report の Speedboard タブに Timeline、コードエディタ内 Ctrl+F 検索、JSON 自動整形 |
| 推奨 | 2026 年 4 月 | Playwright 1.58+ 系。新規プロジェクトはこの系列から |
Playwright vs Cypress vs Selenium vs Puppeteer
| 観点 | Playwright | Cypress | Selenium | Puppeteer |
|---|---|---|---|---|
| ブラウザ | ◎ 3 種(Chromium/Firefox/WebKit) | △ Chromium / Firefox のみ | ◎ すべて | × Chromium のみ |
| auto-waiting | ◎ 標準 | ○ 一部 | × 手動 | × 手動 |
| 並列実行 | ◎ ワーカ並列 | △ 有償版のみ | ○ Hub 経由 | ○ 独自実装 |
| API テスト | ◎ 組込み | △ 一部 | × 非対応 | △ 一部 |
| Trace Viewer | ◎ 完全 | △ 限定 | × | × |
| コンポーネントテスト | ○ 対応 | ◎ 強力 | × | × |
| 言語対応 | TS/JS/Python/.NET/Java | TS/JS のみ | 多言語 | TS/JS のみ |
インストールと初期セットアップ
# 対話形式で雛形生成 npm init playwright@latest # or Bun: bun create playwright # or Deno: deno run -A npm:create-playwright@latest # # ? Do you want to use TypeScript or JavaScript? TypeScript # ? Where to put your end-to-end tests? tests # ? Add a GitHub Actions workflow? y # ? Install Playwright browsers? y # 既存プロジェクトに追加 npm install --save-dev @playwright/test npx playwright install --with-deps # バージョン確認 npx playwright --version
import { defineConfig, devices } from "@playwright/test";
export default defineConfig({
testDir: "./tests",
fullyParallel: true,
forbidOnly: !!process.env.CI, // CI で .only が残っていたら失敗
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 4 : undefined,
reporter: [
["html", { open: "never" }],
["github"], // GitHub Actions 用 inline annotation
["json", { outputFile: "playwright-report/results.json" }],
],
use: {
baseURL: process.env.BASE_URL ?? "http://localhost:3000",
trace: "on-first-retry", // 失敗リトライ時に trace 保存
screenshot: "only-on-failure",
video: "retain-on-failure",
locale: "ja-JP",
timezoneId: "Asia/Tokyo",
},
projects: [
{ name: "chromium", use: { ...devices["Desktop Chrome"] } },
{ name: "firefox", use: { ...devices["Desktop Firefox"] } },
{ name: "webkit", use: { ...devices["Desktop Safari"] } },
{ name: "mobile", use: { ...devices["iPhone 15"] } },
],
// 開発サーバーを自動起動(次の URL が返るまで待つ)
webServer: {
command: "npm run dev",
url: "http://localhost:3000",
reuseExistingServer: !process.env.CI,
timeout: 120_000,
},
});
Locator ── ユーザー視点での要素指定
Playwright のロケーターは「実装詳細(CSS クラス / 構造)」ではなく「ユーザーから見えるもの(役割 / ラベル / テキスト)」を優先します。これにより、スタイル変更や DOM リファクタリングで落ちにくいテストが書けます。
| 優先度 | メソッド | 用途 |
|---|---|---|
| ① 最優先 | getByRole(role, { name }) |
ARIA role(button / link / textbox / heading) |
| ② | getByLabel(text) |
フォーム要素のラベル |
| ③ | getByPlaceholder(text) |
プレースホルダ |
| ④ | getByText(text) |
可視テキスト |
| ⑤ | getByAltText(text) |
alt 属性 |
| ⑥ | getByTitle(text) |
title 属性 |
| ⑦ 最終手段 | getByTestId("id") |
テスト専用 data-testid |
| ✗ 非推奨 | page.locator("button.btn-primary") |
CSS / XPath は詳細結合 |
test("login flow", async ({ page }) => {
await page.goto("/login");
// ラベルで入力欄を特定(スタイル変更の影響を受けない)
await page.getByLabel("メールアドレス").fill("alice@example.com");
await page.getByLabel("パスワード").fill("secret-pw");
// ボタンは role + name で
await page.getByRole("button", { name: "ログイン" }).click();
// 見出しで画面遷移を検証
await expect(page.getByRole("heading", { name: "ダッシュボード" })).toBeVisible();
});
フィルタリングとチェーン
// 商品リストの中から「Product 2」の「Add to cart」だけを押す
const product = page.getByRole("listitem")
.filter({ hasText: "Product 2" });
await product.getByRole("button", { name: "Add to cart" }).click();
// 1 つしかないはずだが複数マッチしたら失敗させる
await page.getByRole("button", { name: "送信" }).click();
// 複数マッチが合法なら first() / last() / nth(n)
await page.getByRole("listitem").first().click();
await page.getByRole("listitem").nth(2).click();
// visible: true で可視要素のみにフィルタ(v1.51+)
await page.getByRole("button", { name: "削除" }).filter({ visible: true }).click();
locator.describe() でトレースを読みやすく(v1.57+)
const submitButton = page
.getByRole("button", { name: "送信" })
.describe("メインフォームの送信ボタン");
await submitButton.click();
// Trace Viewer / HTML Report 上で「メインフォームの送信ボタン」と表示される
Web-first Assertions ── auto-waiting が効く expect
Playwright の expect(locator).xxx() は条件が満たされるまで自動的にリトライします。明示的な waitFor が不要になり、flaky test がほぼ消えます。
// 可視・存在・状態
await expect(banner).toBeVisible();
await expect(modal).toBeHidden();
await expect(submit).toBeEnabled();
await expect(check).toBeChecked();
// テキスト・属性
await expect(h1).toHaveText("ようこそ");
await expect(h1).toContainText("ようこそ");
await expect(link).toHaveAttribute("href", "/home");
await expect(btn).toHaveClass(/primary/);
await expect(btn).toContainClass("primary"); // v1.52+(個別クラス判定が簡潔に)
// 数・URL・タイトル
await expect(page.getByRole("listitem")).toHaveCount(5);
await expect(page).toHaveURL("/dashboard");
await expect(page).toHaveTitle(/ダッシュボード/);
// カスタムタイムアウト(グローバル 5s → 個別 10s)
await expect(slowItem).toBeVisible({ timeout: 10_000 });
expect().not を使った否定アサーションに注意: await expect(elem).not.toBeVisible() はタイムアウト全体分「見えないこと」を待ちます。「最初から存在しない要素」を確認する場合もデフォルト 5 秒待つため、テスト時間が伸びます。明らかに即確認したいケースは { timeout: 1000 } を渡すか、await elem.isHidden() で即時判定にしてください。テストの基本構造 ── test / describe / hooks
import { test, expect } from "@playwright/test";
test.describe("認証フロー", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/");
});
test.afterEach(async ({ page }, testInfo) => {
// 失敗時のみスクリーンショットを artifact に添付
if (testInfo.status !== "passed") {
await page.screenshot({ path: `fail-${testInfo.title}.png` });
}
});
test("正しい認証情報でログインできる", async ({ page }) => {
await page.getByRole("link", { name: "ログイン" }).click();
await page.getByLabel("メール").fill("alice@example.com");
await page.getByLabel("パスワード").fill("correct-pw");
await page.getByRole("button", { name: "ログイン" }).click();
await expect(page).toHaveURL("/dashboard");
await expect(page.getByText("ようこそ, Alice")).toBeVisible();
});
test("誤ったパスワードはエラー表示", async ({ page }) => {
await page.getByRole("link", { name: "ログイン" }).click();
await page.getByLabel("メール").fill("alice@example.com");
await page.getByLabel("パスワード").fill("wrong-pw");
await page.getByRole("button", { name: "ログイン" }).click();
await expect(page.getByRole("alert")).toContainText("パスワードが違います");
});
// 並列モード切替(ファイル単位で直列にしたい場合)
test.describe.configure({ mode: "serial" });
});
storageState ── ログイン状態を全テストで共有
毎テストごとにログインすると CI 時間が増えるので、セットアップでログインして storageState を保存 → 本テストは読み込んで再利用するのが定石です。Cookie・LocalStorage・IndexedDB(v1.51+)まで保存されます。
import { test as setup, expect } from "@playwright/test";
const authFile = ".auth/user.json";
setup("authenticate", async ({ page }) => {
await page.goto("/login");
await page.getByLabel("メール").fill(process.env.E2E_EMAIL!);
await page.getByLabel("パスワード").fill(process.env.E2E_PASSWORD!);
await page.getByRole("button", { name: "ログイン" }).click();
await expect(page).toHaveURL("/dashboard");
// Cookie / LocalStorage / IndexedDB を丸ごとダンプ
await page.context().storageState({ path: authFile });
});
export default defineConfig({
projects: [
// 1) セットアップ専用プロジェクト
{
name: "setup",
testMatch: /global\.setup\.ts/,
},
// 2) 通常のテストは setup 後に走る + storageState を使う
{
name: "chromium",
dependencies: ["setup"],
use: {
...devices["Desktop Chrome"],
storageState: ".auth/user.json",
},
},
],
});
storageState が正しく再現されます。古い Playwright ではこの部分が落ちていたため、v1.51 以降へ上げる動機として大きいです。Fixtures ── test.extend でカスタム依存性注入
Fixtures は「テスト関数に何を渡すか」を宣言的に定義する仕組みで、ログイン済み User・API Client・DB クライアントなどを必要なテストにだけ自動注入できます。
import { test as base, expect } from "@playwright/test";
type Fixtures = {
apiClient: { get: (url: string) => Promise<any> };
todoPage: import("./todo-page").TodoPage;
};
export const test = base.extend<Fixtures>({
// 各テストで API 呼び出しできる軽量クライアント
apiClient: async ({ request }, use) => {
await use({
async get(url) {
const res = await request.get(url);
return await res.json();
},
});
},
// Page Object Model を fixture として提供
todoPage: async ({ page }, use) => {
const { TodoPage } = await import("./todo-page");
const todoPage = new TodoPage(page);
await todoPage.goto();
await use(todoPage);
},
});
export { expect };
import { test, expect } from "../fixtures/test-fixtures";
test("TODO を追加できる", async ({ todoPage }) => {
await todoPage.addTodo("レポートを書く");
await expect(todoPage.listItem("レポートを書く")).toBeVisible();
});
test("API で残数を確認", async ({ apiClient }) => {
const data = await apiClient.get("/api/todos/stats");
expect(data.pending).toBeGreaterThan(0);
});
Box Fixtures(v1.51+)── 実装詳細をレポートから隠す
export const test = base.extend<{ adminClient: unknown }>({
adminClient: [async ({}, use) => {
// 中身はテストレポートの step tree に出さない
await use(createAdminClient());
}, { box: true, title: "Admin API クライアント" }],
});
Page Object Model ── 巨大アプリでの保守性
import type { Locator, Page } from "@playwright/test";
export class TodoPage {
constructor(private readonly page: Page) {}
readonly input = this.page.getByPlaceholder("やることを入力");
readonly list = this.page.getByRole("list", { name: "TODO 一覧" });
async goto() { await this.page.goto("/todos"); }
listItem(name: string): Locator {
return this.list.getByRole("listitem").filter({ hasText: name });
}
async addTodo(text: string) {
await this.input.fill(text);
await this.input.press("Enter");
}
async toggleDone(name: string) {
await this.listItem(name).getByRole("checkbox").check();
}
async deleteTodo(name: string) {
await this.listItem(name).getByRole("button", { name: "削除" }).click();
}
}
const page = new TodoPage() を書く」手間が残ります。fixture として提供すれば test("...", async ({ todoPage }) => {}) だけで使えます。大規模プロジェクトでは POM と fixture をセットで設計するのが標準パターンです。Codegen / UI Mode / Trace Viewer ── 三大ツール
Codegen ── 操作を記録してコード生成
npx playwright codegen http://localhost:3000 # ブラウザと Playwright Inspector が開く # 画面を操作するだけで対応する TS コードが Inspector に生成される # v1.55+ はクリック操作のあとに toBeVisible / toHaveText 等を自動提案 # 完了したらコピーしてテストファイルに貼り付け
UI Mode ── 視覚的にテストを走らせる
npx playwright test --ui # 機能: # - テストツリーから選んで実行 # - タイムトラベル(過去の任意のステップに戻れる) # - Locator Pick(画面からクリックでロケーター取得) # - Watch モード(ファイル保存で自動再実行) # - ネットワークパネル、コンソール、ソース表示 # - v1.58+ は JSON レスポンスの自動整形、コードエディタ内 Ctrl+F 検索
Trace Viewer ── 失敗を 100% 再現
# trace: "on-first-retry" 設定済みなら CI で自動収集される # ローカルで強制収集したい場合 npx playwright test --trace on # trace ファイルを開く npx playwright show-trace test-results/.../trace.zip # HTML Report 経由でも開ける npx playwright show-report
Copy Prompt ── LLM デバッグ(v1.51+)
HTML Report / Trace Viewer / UI Mode のエラー画面に「Copy Prompt」ボタンがあり、エラー文脈とスタックを LLM 用プロンプトとして一発コピーできます。Claude や ChatGPT に貼り付ければ原因解析と修正案が即得られます。Claude Code との連携は Claude Code で Playwright と Browser Use を使うブラウザ自動操作ガイド を参照してください。
API テスト ── ブラウザを立ち上げずに REST を叩く
import { test, expect } from "@playwright/test";
test.describe("REST API", () => {
test("GET /api/posts", async ({ request }) => {
const res = await request.get("/api/posts");
expect(res.status()).toBe(200);
const body = await res.json();
expect(Array.isArray(body)).toBe(true);
});
test("POST /api/posts で新規作成", async ({ request }) => {
const res = await request.post("/api/posts", {
data: { title: "test", body: "content" },
headers: { "Content-Type": "application/json" },
});
expect(res.status()).toBe(201);
const body = await res.json();
expect(body.id).toBeDefined();
});
});
storageState を作り、残りの UI テストはそこから走らせる、という設計が最高速です。ブラウザ操作でのログインを毎回省略できるため CI 時間が劇的に減ります。コンポーネントテスト
# React の場合 npm init playwright@latest --ct # or Vue / Svelte / Solid 用の別パッケージ npx playwright test --ui
import { test, expect } from "@playwright/experimental-ct-react";
import { Button } from "./Button";
test("variant prop が適用される", async ({ mount }) => {
const component = await mount(
<Button variant="primary">保存</Button>
);
await expect(component).toContainClass("bg-primary-500");
await expect(component).toHaveText("保存");
});
test("onClick が呼ばれる", async ({ mount }) => {
let clicked = 0;
const component = await mount(
<Button onClick={() => clicked++}>Click me</Button>
);
await component.click();
expect(clicked).toBe(1);
});
Aria Snapshots と Visual Regression
Aria Snapshot(v1.49+)── アクセシビリティツリー比較
await expect(page.locator("main")).toMatchAriaSnapshot(`
- heading "ようこそ" [level=1]
- navigation:
- link "ホーム"
- link "設定"
- button "新規作成"
`);
toHaveScreenshot ── ピクセル比較
test("ランディングページのデザイン", async ({ page }) => {
await page.goto("/");
await expect(page).toHaveScreenshot("landing.png", {
maxDiffPixelRatio: 0.01,
fullPage: true,
mask: [page.locator(".dynamic-time")], // 時刻表示など動的部分をマスク
});
});
# 初回は --update-snapshots を付けて正解画像を保存 npx playwright test --update-snapshots # 以降は変更検知したら失敗する npx playwright test
並列実行とシャーディング ── CI 時間を桁違いに短縮
# ローカルでもワーカ並列が既定(workers: 自動) npx playwright test --workers 8 # CI で複数マシンに分散(4 マシン構成) npx playwright test --shard=1/4 # マシン 1 npx playwright test --shard=2/4 # マシン 2 npx playwright test --shard=3/4 # マシン 3 npx playwright test --shard=4/4 # マシン 4 # レポートを後で合体させる npx playwright merge-reports --reporter=html ./all-blob-reports
GitHub Actions での CI 統合
name: E2E Tests
on:
push: { branches: [main] }
pull_request:
jobs:
e2e:
timeout-minutes: 30
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with: { node-version: 22, cache: npm }
- run: npm ci
- name: Playwright ブラウザ
run: npx playwright install --with-deps chromium firefox webkit
- name: E2E 実行(シャード ${{ matrix.shard }}/4)
run: npx playwright test --shard=${{ matrix.shard }}/4 --reporter=blob
env:
BASE_URL: http://localhost:3000
E2E_EMAIL: ${{ secrets.E2E_EMAIL }}
E2E_PASSWORD: ${{ secrets.E2E_PASSWORD }}
- uses: actions/upload-artifact@v4
if: always()
with:
name: blob-${{ matrix.shard }}
path: blob-report
retention-days: 3
merge-reports:
if: always()
needs: [e2e]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with: { node-version: 22 }
- run: npm ci
- uses: actions/download-artifact@v4
with: { pattern: blob-*, merge-multiple: true, path: all-blob-reports }
- run: npx playwright merge-reports --reporter=html all-blob-reports
- uses: actions/upload-artifact@v4
with: { name: html-report, path: playwright-report, retention-days: 7 }
mcr.microsoft.com/playwright:v1.58.0-noble を CI ジョブのコンテナにすればブラウザインストール不要になり、5〜10 秒の起動短縮になります。GitHub Actions の詳細は GitHub Actions 完全ガイド を参照してください。落とし穴と注意点
CSS Locator を使い続けてテストが壊れやすい
page.locator("button.btn-primary.rounded") のように CSS クラスで要素を取ると、Tailwind のクラスが増減しただけで落ちます。getByRole("button", { name: "保存" }) のようにユーザー視点のロケーターに置き換えれば、実装のリファクタリングで壊れなくなります。Tailwind v4 で @theme を入れ替えた場合も E2E テストは無傷です(Tailwind CSS v4 完全ガイド)。
await 忘れ
Playwright の API はほぼすべて Promise を返します。page.click() のように await を付け忘れると、アクションが実行されないまま次に進んで「なぜかボタンが押されない」と悩みます。ESLint の no-floating-promises を必ず有効化してください(Biome 完全ガイド の Type Inference でも検出可能)。
非同期の手動 wait(waitForTimeout)
await page.waitForTimeout(2000) のような固定ウェイトはテスト時間の無駄遣いであり、ネットワーク遅延で失敗する原因にもなります。Playwright の expect(...) は auto-waiting するので、「要素が表示されるのを待つ」は expect(locator).toBeVisible() に置き換えます。
テスト間で DB を共有
テストがお互いに DB を介して依存すると、並列実行や順序入れ替えで壊れます。基本は各テストで独立した状態をセットアップ、難しければ test.describe.configure({ mode: "serial" }) で直列化して、できればテストごとに専用スキーマ / 一時 DBを使うのが理想です。
.only / .skip を残してコミット
test.only(...) を仕込んだままコミットすると他のテストがスキップされます。設定 forbidOnly: !!process.env.CI を入れると、CI で .only があった瞬間に失敗するため必ず気づけます。Git pre-commit hook に組み込むとさらに安全です(GitHub Actionsでも同じ指針)。
Webkit の時差や挙動差
Chromium では通るテストが WebKit だけ落ちる、というケースがあります。原因はタイムゾーン・ロケール・font rendering・CSS の微細な差。playwright.config.ts で locale: "ja-JP" / timezoneId: "Asia/Tokyo" を明示、toHaveScreenshot は maxDiffPixelRatio を許容値に設定する、が対処法です。
storageState の期限切れ
Cookie の有効期限が短いサイトでは、.auth/user.json に保存したトークンが CI 実行時には期限切れになっていることがあります。setup プロジェクトを毎回走らせて再ログインするか、storageState.expires を確認して期限前なら再利用、という制御を入れてください。
よくある質問
getByRole / getByLabel / getByText で要素を特定できないか検討し、それでも無理(画像ボタンでテキストなし、複雑な SVG ベースの UI 等)な場合の最終手段として data-testid を埋め込みます。実装に専用属性を追加する時点でテストのカップリングが増えるため、乱用すると UI リファクタリング時の変更範囲が広がります。setup プロジェクトで API を叩いてトークン取得、② その結果を Cookie や LocalStorage に詰めて storageState として保存、③ 本テストは storageState を使ってブラウザ UI を開くだけ。UI からログインするより10〜30 倍高速で、CI 時間が劇的に縮みます。mcr.microsoft.com/playwright)でブラウザインストール省略、③ storageState でログイン省略、④ retry を 1〜2 回に絞る(3 以上は flaky の隠蔽になる)、⑤ trace: “on-first-retry” で成功テストは trace を保存しない、⑥ 依存キャッシュ(actions/setup-node cache: npm)。GitHub Actions での具体構成は GitHub Actions 完全ガイドを参照してください。test.extend で提供すると、テスト側は async ({ loginPage }) => {} のように 1 引数で使えるスッキリしたコードになります。大規模プロジェクトほどこの組合せが効いてきます。bunx playwright test で動くケースもありますが、公式サポート外なので CI では Node 22 を使うのが無難です。まとめ
- 2026 年の E2E デファクト: Playwright 1.58+。3 ブラウザ 1 API・auto-waiting・Trace Viewer で Flaky test が過去のものに
- Locator はユーザー視点:
getByRole(最優先)→getByLabel→getByText→getByTestId(最終手段) - Web-first Assertions:
expect(locator).toBeVisible()等が auto-waiting。toContainClass()(v1.52+)・toMatchAriaSnapshot()(v1.49+)も追加 - Fixtures と Page Object Modelで保守性を担保。
box: trueで内部詳細を隠す - storageState でログイン共有: IndexedDB にも対応(v1.51+)。
setupプロジェクト + dependencies の構成 - Codegen / UI Mode / Trace Viewerが三大ツール。失敗の再現と原因特定が劇的に楽に
- Copy Prompt(v1.51+)で LLM にエラー解析を投げられる。Claude Code との連携も強力
- Sharding + Docker 公式イメージで CI 時間を桁違いに短縮
- 落とし穴は CSS Locator・await 忘れ・waitForTimeout・test.only・WebKit 差分・storageState 期限
Claude Code との連携は Claude Code で Playwright と Browser Use を使うブラウザ自動操作ガイド、CI/CD は GitHub Actions 完全ガイド、対象アプリのフレームワーク別記事は React 19・Svelte 5・Astro・Nuxt 4・Claude Code × Next.js、ツール周辺は Tailwind CSS v4・Biome・Bun・Deno 2、UI コンポーネント検証は Claude Code × Storybook もあわせて、Playwright を核に据えた 2026 年型テスト基盤を構築してください。