跳轉到

3.2 Fixtures:beforeEach 與共用準備#

問題:每個測試都要重複準備#

十個測試都要先登入,難道要複製貼上十遍?

beforeEach:每個測試前自動執行#

import { test, expect } from "@playwright/test";

test.describe("購物車", () => {
  test.beforeEach(async ({ page }) => {
    // 每個測試前都先登入並進到購物車頁
    await page.goto("https://my-site.com/login");
    await page.getByLabel("電子郵件").fill("user@test.com");
    await page.getByLabel("密碼").fill("password123");
    await page.getByRole("button", { name: "登入" }).click();
    await expect(page).toHaveURL(/dashboard/);

    await page.getByRole("link", { name: "購物車" }).click();
  });

  test("加入商品後數量應該更新", async ({ page }) => {
    await page.getByRole("button", { name: "加入購物車" }).click();
    await expect(page.getByText("1 件商品")).toBeVisible();
  });

  test("清空購物車", async ({ page }) => {
    await page.getByRole("button", { name: "清空" }).click();
    await expect(page.getByText("購物車是空的")).toBeVisible();
  });
});

其他相似工具:

test.beforeAll(async () => {  });   // 整個檔案跑一次(開測試前)
test.afterEach(async () => {  });   // 每個測試後(清理)
test.afterAll(async () => {  });    // 整個檔案結束後(清理)

存取測試資料:fixtures 的參數#

test 的第一個參數物件提供內建 fixtures:

test("範例", async ({ page, browserName, viewport }) => {
  // page:頁面物件(最常用)
  // browserName:瀏覽器名稱(chromium/firefox/webkit)
  // viewport:視窗大小
});

共用的登入 helper(跨檔案重複時)#

多個測試檔都要登入?抽出 helper 函式:

// tests/helpers/login.ts
import { expect, type Page } from "@playwright/test";

export async function login(page: Page) {
  await page.goto("https://my-site.com/login");
  await page.getByLabel("電子郵件").fill("user@test.com");
  await page.getByLabel("密碼").fill("password123");
  await page.getByRole("button", { name: "登入" }).click();
  await expect(page).toHaveURL(/dashboard/);
}
// tests/cart.spec.ts
import { test, expect } from "@playwright/test";
import { login } from "./helpers/login";

test.beforeEach(async ({ page }) => {
  await login(page);
});

分工原則#

情境 用什麼
同一個檔案內的共用準備 beforeEach
跨檔案共用的操作 helper 函式
每個測試都需要、且與頁面狀態相關 自訂 fixture(進階)

原則:準備工作抽出去,測試本體只留「操作 + 斷言」。這樣每個測試一打開就是重點,好讀好維護。