本文へスキップ
Typle
ログイン状態を確認中

プログラミング · Playwright · テスト

Playwright構文のタイピング練習

Playwright Test のテストの書き方70個を、初級・上級の2つのリストで打って覚えます。page.goto、getByRole、toBeVisible などを、TypeScript のコードの形で練習できます。

2リスト・70語

無料・ログインなしで練習できます。押すとこのパックをフォローし、すぐに練習が始まります。

収録している言葉

Playwright構文(初級)

打つ言葉意味・補足
// Playwright Test / TypeScript対象環境:例の前提(@playwright/testを使用。Webアプリ・画面文言・APIパス等はサンプル。相対URLはbaseURL設定が必要)
import { test, expect } from '@playwright/test';import:テストAPIをimport(Jestのexpectとは別)
test.only('調査中', async ({ page }) => {});test.only:実行対象を限定(コミット前に解除。CIではforbidOnlyを推奨)
test.use({ viewport: { width: 1280, height: 720 } });test.use:グループ等のfixture設定(テスト本体の外で設定)
await page.goto('/login');page.goto:ページへ移動(相対URLはbaseURLが必要)
const email = page.getByLabel('メール', { exact: true });getByLabel:ラベルで入力欄を探す
const search = page.getByPlaceholder('検索');getByPlaceholder:プレースホルダーで探す
const message = page.getByText('保存しました', { exact: true });getByText:テキストで探す(複数一致に注意)
const card = page.getByTestId('user-card');getByTestId:テストIDで探す(既定はdata-testid)
const logo = page.getByAltText('ロゴ');getByAltText:画像等の代替テキスト
const form = page.locator('form#login');locator:CSS等で探す(壊れやすいDOM構造依存を避ける)
const second = page.getByRole('listitem').nth(1);nth / first / last:位置で選ぶ(0始まり。曖昧さを位置で隠さず意味で絞る)
await page.getByRole('button', { name: '保存' }).click();click:クリック(Locatorは操作可能性を自動待機)
await page.getByLabel('メール').fill('pomo@example.com');fill:入力値を置き換える
await page.getByLabel('言語').selectOption('ja');selectOption:selectの選択肢を選ぶ(HTML select向け。独自ドロップダウンとは別)
await page.getByRole('button', { name: 'メニュー' }).hover();hover:マウスを乗せる
await expect(page.getByTestId('loading')).toBeHidden();toBeHidden:非表示または未接続を検証
await expect(page.getByTestId('status')).toHaveText('保存済み');toHaveText:テキスト一致
await expect(page.getByTestId('message')).toContainText('完了');toContainText:テキストを含む
await expect(page.getByRole('listitem')).toHaveCount(3);toHaveCount:一致する要素数(即時取得したcountへの汎用expectより安定)
await expect(page.getByTestId('error')).not.toBeVisible();not:否定
await expect(page).toHaveScreenshot('home.png');toHaveScreenshot:画像比較(初回基準画像と更新差分をレビュー。OS・フォント等の環境をそろえる)
await expect(page.getByTestId('loaded')).toBeVisible();待機の基本:状態を待つ(固定のwaitForTimeoutやnetworkidleを万能な完了条件にしない)
await page.route('**/api/users', route => route.abort());route.abort:通信を失敗させる(異常系の検証)
await page.route('**/api/users', route => route.continue());route.continue:通信を続行(登録したroute内)
test.use({ storageState: 'playwright/.auth/user.json' });test.use({ storageState }):認証状態を再利用(事前に生成。セッション期限・サーバー側状態に依存)
npx playwright installplaywright install:ブラウザーを導入(ターミナル。CI等では--with-depsを検討)
npx playwright testplaywright test:テスト実行(ターミナル)
npx playwright test --ui--ui / --headed / --debug:UI・画面表示・デバッグ(ターミナル)
npx playwright test --headed--ui / --headed / --debug:UI・画面表示・デバッグ(ターミナル)
npx playwright test --debug--ui / --headed / --debug:UI・画面表示・デバッグ(ターミナル)
npx playwright test --project=chromium--project / -g:プロジェクト・テスト名で絞る(プロジェクト名は設定と一致)
npx playwright test -g 'ログイン'--project / -g:プロジェクト・テスト名で絞る(プロジェクト名は設定と一致)
npx playwright show-reportshow-report / codegen:レポート・操作からコード生成(生成コードもLocator・アサーション・機密情報をレビュー)
npx playwright codegen http://localhost:3000show-report / codegen:レポート・操作からコード生成(生成コードもLocator・アサーション・機密情報をレビュー)

Playwright構文(上級)

打つ言葉意味・補足
test('トップページ', async ({ page }) => { await page.goto('/'); await expect(page.getByRole('heading', { name: 'ホーム' })).toBeVisible(); });test:ブラウザーテストを定義(pageはテストごとに準備されるfixture)
test.describe('ログイン', () => { test('フォーム表示', async ({ page }) => { await page.goto('/login'); await expect(page.getByLabel('メール')).toBeVisible(); }); });test.describe:グループ化
test.beforeEach(async ({ page }) => { await page.goto('/'); });test.beforeEach:各テスト前に実行
test.afterEach(async ({ page }, testInfo) => { if (testInfo.status !== testInfo.expectedStatus) { await testInfo.attach('failure', { body: await page.screenshot(), contentType: 'image/png' }); } });test.afterEach:各テスト後に実行(成果物に認証情報・個人情報が含まれないか確認)
await test.step('フォーム入力', async () => { await page.getByLabel('メール').fill('pomo@example.com'); });test.step:処理をレポート上で区切る(test内の例)
test.skip('未対応', async ({ page }) => {}); test.fixme('修正待ち', async ({ page }) => {});test.skip / test.fixme:スキップ・修正待ち(放置しない)
const save = page.getByRole('button', { name: '保存', exact: true });getByRole:役割とアクセシブル名で探す(利用者から見える契約を優先)
const row = page.getByRole('row').filter({ hasText: 'Pomo' }); await row.getByRole('button', { name: '編集' }).click();Locator連結 / filter:候補を絞る(filterで一意になるようにする)
const card = page.getByTestId('card').filter({ has: page.getByRole('heading', { name: 'Pomo', exact: true }) });filter({ has }):子要素で絞る(hasのLocatorは外側を基準に評価)
await page.frameLocator('#payment').getByLabel('カード番号').fill('test-value');frameLocator:iframe内を操作(対象iframeを準備。実決済用の例ではない)
await page.getByRole('textbox', { name: '検索' }).press('Enter');press:キー入力
await page.getByRole('textbox', { name: '検索' }).pressSequentially('hello');pressSequentially:キーを順に入力(キーイベントが必要な場合。通常はfillを優先)
await page.getByRole('checkbox', { name: '同意する' }).check();check / uncheck:チェック状態を設定
await page.getByLabel('添付').setInputFiles('tests/fixtures/sample.txt');setInputFiles:ファイルを選択(ファイルが必要。相対パスは実行ディレクトリ基準)
await page.getByTestId('item').dragTo(page.getByTestId('drop-zone'));dragTo:ドラッグ(アプリのドラッグ実装に依存)
page.once('dialog', dialog => dialog.accept()); await page.getByRole('button', { name: '削除' }).click();dialog:ダイアログへ応答(リスナーは操作前に登録。実際に削除する画面ではテストデータを使用)
const popupPromise = page.waitForEvent('popup'); await page.getByRole('link', { name: '詳細' }).click(); const popup = await popupPromise; await expect(popup).toHaveURL(/detail/);popup:新規ページを取得(待機を操作前に登録)
const downloadPromise = page.waitForEvent('download'); await page.getByRole('button', { name: 'CSV出力' }).click(); const download = await downloadPromise; await download.saveAs(testInfo.outputPath(download.suggestedFilename()));download:ダウンロードを取得(testコールバックの第2引数等でtestInfoを受け取る)
await expect(page.getByText('完了', { exact: true })).toBeVisible();toBeVisible:表示されるまで検証(自動リトライするのでawait)
await expect(page.getByLabel('メール')).toHaveValue('pomo@example.com');toHaveValue:入力値
await expect(page.getByRole('button', { name: '送信' })).toBeEnabled();toBeEnabled / toBeDisabled:有効・無効
await expect(page.getByRole('checkbox', { name: '同意する' })).toBeChecked();toBeChecked:チェック状態
await expect(page.getByRole('link', { name: 'ヘルプ' })).toHaveAttribute('href', '/help');toHaveAttribute:属性値
await expect(page).toHaveURL(/dashboard/); await expect(page).toHaveTitle(/マイページ/);toHaveURL / toHaveTitle:URL・ページタイトル
await expect.soft(page.getByTestId('status')).toHaveText('完了');expect.soft:失敗後も続ける検証(テスト自体は失敗扱いになる)
await expect.poll(async () => { const response = await request.get('/api/status'); const body = await response.json(); return body.state; }).toBe('ready');expect.poll:値を再取得して検証(request fixtureとAPIが必要)
await page.route('**/api/users', route => route.fulfill({ json: [{ id: 1, name: 'Pomo' }] })); await page.goto('/users');page.route / fulfill:通信をモック(対象リクエストより前に登録)
const responsePromise = page.waitForResponse(r => r.url().endsWith('/api/users') && r.request().method() === 'POST'); await page.getByRole('button', { name: '保存' }).click(); const response = await responsePromise; expect(response.ok()).toBeTruthy();waitForResponse:特定レスポンスを待つ(待機を操作前に登録。画面結果も別途検証)
const response = await request.post('/api/users', { data: { name: 'Pomo' } }); await expect(response).toBeOK();request.get / post:APIを直接呼ぶ(request fixtureを受け取る。テストデータを後片付け)
const response = await request.delete('/api/users/1'); await expect(response).toBeOK();request.delete:APIでテストデータを削除(専用テスト環境と対象IDを使用)
await page.context().storageState({ path: 'playwright/.auth/user.json' });storageState:認証状態を保存(機密情報を含む。gitへコミットしない)
import { test as base } from '@playwright/test'; const test = base.extend<{ appName: string }>({ appName: async ({}, use) => { await use('Sample'); } });test.extend:独自fixtureを作る(TypeScript例。準備・後片付けをuseの前後に配置)
import { defineConfig } from '@playwright/test'; export default defineConfig({ testDir: './tests', forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, use: { baseURL: 'http://localhost:3000', trace: 'retain-on-failure', screenshot: 'only-on-failure' } });defineConfig:テスト実行設定(playwright.config.ts。再試行で不安定なテストを放置しない)
webServer: { command: 'npm run dev', url: 'http://localhost:3000', reuseExistingServer: !process.env.CI }webServer:アプリ起動を管理(defineConfig内の断片)
import { devices } from '@playwright/test'; /* defineConfig内: */ /* projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }] */projects / devices:複数ブラウザー等で実行(ブラウザーのインストールが必要)

ほかの公式パックを見る