端到端測試
規則
- 使用 Playwright 進行端到端測試 — 跨瀏覽器、自動等待、內建測試執行器、出色的 CI 支援
- 定位器優先順序:
getByRole() > getByLabel() > getByPlaceholder() > getByTestId() > CSS 選擇器
- 頁面物件模型:將頁面互動封裝在類別中 —
LoginPage.login(email, password)
- 測試隔離:每個測試從全新狀態開始 — 使用
beforeEach 進行設定,避免測試相互依賴
- 自動等待:Playwright 會自動等待元素 — 不要加入手動的
waitForTimeout() 呼叫
- 斷言:使用
expect(locator) 的 web-first 斷言 — toBeVisible()、toHaveText()、toHaveURL()
- 平行執行:預設情況下測試會平行執行 — 確保測試之間沒有共享的可變狀態
- CI:在無頭模式下執行,配置重試機制(CI 中設定
retries: 2),並在失敗時上傳追蹤
- 視覺回歸:
expect(page).toHaveScreenshot() — 使用 --update-snapshots 更新基準
模式
class LoginPage {
constructor(private page: Page) {}
async goto() { await this.page.goto("/login"); }
async login(email: string, password: string) {
await this.page.getByLabel("電子郵件").fill(email);
await this.page.getByLabel("密碼").fill(password);
await this.page.getByRole("button", { name: "登入" }).click();
await this.page.waitForURL("/dashboard");
}
}
export default defineConfig({
retries: process.env.CI ? 2 : 0,
use: { trace: "on-first-retry", screenshot: "only-on-failure" },
projects: [
{ name: "chromium", use: { ...devices["Desktop Chrome"] } },
{ name: "mobile", use: { ...devices["Pixel 5"] } },
],
});
應避免
page.waitForTimeout() — 改用自動等待或 waitForURL()、waitForResponse()
- 對互動元素使用 CSS 選擇器 — 改用基於角色的定位器以獲得更高的穩定性
- 依賴其他測試狀態的測試 — 每個測試必須能夠獨立執行
- 直接測試第三方服務 — 使用
page.route() 模擬外部 API
- 跳過行動裝置視埠 — 在專案矩陣中至少測試一部行動裝置