Playwright 入門 — 從 0 到第一個能跑的 E2E(30 分鐘上手)
如果你已經會寫手動 test case,學 Playwright 就是把同樣的步驟用 code 寫出來。難點不在 API,在「怎麼選元素」跟「怎麼等對的東西」。
為什麼選 Playwright
| 對手 | 弱點 |
|---|---|
| Selenium | API 老派、wait 很麻煩、要自己裝 driver |
| Cypress | 只支援 Chromium、沒 multi-tab、跨 origin 麻煩 |
| Puppeteer | 純 Chromium、沒測試 runner |
Playwright 強項:原生支援 Chromium/Firefox/WebKit、auto-wait、trace viewer 神器、TypeScript 一等公民。新案直接選它。
30 分鐘從 0 到 1
1. 安裝(2 分鐘)
npm init -y
npm init playwright@latest
CLI 會問你:
- TypeScript or JavaScript?→ TypeScript(型別檢查抓 bug)
- 測試放哪?→ 預設
tests/ - GitHub Actions workflow?→ Yes(之後就有 CI 模板)
- Install browsers?→ Yes
裝完看到 tests/example.spec.ts 跟 playwright.config.ts 就成功。
2. 跑第一個範例(1 分鐘)
npx playwright test
跑完開報告:
npx playwright show-report
3. 寫自己的測試(10 分鐘)
新增 tests/login.spec.ts:
import { test, expect } from '@playwright/test';
test('登入失敗顯示錯誤訊息', async ({ page }) => {
await page.goto('https://yourapp.com/login');
await page.getByLabel('Email').fill('[email protected]');
await page.getByLabel('Password').fill('wrong-password');
await page.getByRole('button', { name: '登入' }).click();
await expect(page.getByText('帳號或密碼錯誤')).toBeVisible();
});
跑:
npx playwright test login.spec.ts
恭喜,第一支跑起來了。
Selector 怎麼選(最關鍵)
新手最常犯的錯:用 CSS selector .btn-primary。class 改了測試就壞。
優先順序:
getByRole— 最穩,跟著無障礙樹走,UI 怎麼改都對typescript page.getByRole('button', { name: '送出' })getByLabel— 表單欄位首選typescript page.getByLabel('使用者名稱')getByText— 純文字內容typescript page.getByText('購物車(3)')getByTestId— 上面都不行才用,且要跟前端團隊約好data-testid規範typescript page.getByTestId('checkout-button')
禁忌:page.locator('.css-1a2b3c')(CSS-in-JS 雜湊每次 build 都變)、page.locator('div > div:nth-child(3) > button')(DOM 微調就壞)。
Auto-wait — 不用自己寫 sleep
// ❌ 舊習慣
await page.waitForTimeout(2000);
await page.click('.button');
// ✅ Playwright 寫法
await page.getByRole('button', { name: '送出' }).click();
// Playwright 自動等到元素:可見、enabled、stable、能被點擊
expect() 也自動 retry:
await expect(page.getByText('訂單已建立')).toBeVisible({ timeout: 10000 });
// 預設 5 秒內每 100ms retry 一次
結論:忘掉 sleep,用 expect.toBeVisible() 等狀態。
Debug 三神器
--headed— 看著瀏覽器跑bash npx playwright test --headed --workers=1--debug— Playwright Inspector,逐步執行bash npx playwright test login.spec.ts --debug- Trace Viewer — fail 後重現
bash # playwright.config.ts 設定 trace: 'on-first-retry' npx playwright show-trace trace.zipTrace viewer 會錄下每步的 DOM snapshot、network、console,比影片有用十倍。
CI 整合(GitHub Actions)
init 已幫你生 .github/workflows/playwright.yml:
name: Playwright Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 7
PR 提交就跑、fail 上傳 report、點下載就能 debug。
新手避雷
- 不要每個 test 都
goto— 用beforeEach或storageState重用登入。 - 不要測 third-party 細節 — 別把 Google OAuth 內頁也寫進去,會被改死。
- selector 用 page object 包起來 — 5 個檔案以上就抽
LoginPageclass,selector 改一處就好。 - flaky test 不要忽略 — 通常是 race condition,加 retry 只是蓋住問題。
- 跨瀏覽器先別開全 — 起步先 Chromium,等穩定再加 Firefox/WebKit。
下一步
- 學
fixtures重用登入狀態 - 學
expect(page).toHaveScreenshot()做視覺迴歸 - 學
requestAPI 直接打 API 不開瀏覽器(測 API + UI 混合)
學會選 selector + 用 auto-wait + 看懂 trace,你就會用 Playwright 了。剩下都是熟練度。