All checks were successful
ERP-Deploy-Demo / deploy-demo (push) Successful in 1m36s
7.6 KiB
7.6 KiB
name, description
| name | description |
|---|---|
| E2E 端到端測試規範 (E2E Testing with Playwright) | 規範 Playwright 端到端測試的撰寫慣例、目錄結構、共用工具與執行方式,確保所有 E2E 測試保持一致性與可維護性。 |
E2E 端到端測試規範 (E2E Testing with Playwright)
本技能定義了 Star ERP 系統中端到端 (E2E) 測試的實作標準,使用 Playwright 模擬真實使用者操作瀏覽器,驗證 UI 顯示與功能流程的正確性。
1. 專案結構
1.1 目錄配置
star-erp/
├── playwright.config.ts # Playwright 設定檔
├── e2e/ # E2E 測試根目錄
│ ├── helpers/ # 共用工具函式
│ │ └── auth.ts # 登入 helper
│ ├── screenshots/ # 測試截圖存放
│ ├── auth.spec.ts # 認證相關測試(登入、登出)
│ ├── inventory.spec.ts # 庫存模組測試
│ ├── products.spec.ts # 商品模組測試
│ └── {module}.spec.ts # 依模組命名
├── playwright-report/ # HTML 測試報告(自動產生,已 gitignore)
└── test-results/ # 失敗截圖與錄影(自動產生,已 gitignore)
1.2 命名規範
| 項目 | 規範 | 範例 |
|---|---|---|
| 測試檔案 | 小寫,依模組命名 .spec.ts |
inventory.spec.ts |
| 測試群組 | test.describe('中文功能名稱') |
test.describe('庫存查詢') |
| 測試案例 | 中文描述「應」開頭 | test('應顯示庫存清單') |
| 截圖檔案 | {module}-{scenario}.png |
inventory-search-result.png |
2. 設定檔 (playwright.config.ts)
2.1 核心設定
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './e2e',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: 'http://localhost:8081', // Sail 開發伺服器
screenshot: 'only-on-failure', // 失敗時自動截圖
video: 'retain-on-failure', // 失敗時保留錄影
trace: 'on-first-retry', // 重試時收集 trace
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
});
2.2 重要注意事項
Important
baseURL必須指向本機 Sail 開發伺服器(預設http://localhost:8081)。 確保測試前已執行./vendor/bin/sail up -d與./vendor/bin/sail npm run dev。
3. 共用工具 (Helpers)
3.1 登入 Helper
位置:e2e/helpers/auth.ts
import { Page } from '@playwright/test';
/**
* 共用登入函式
* 使用測試帳號登入 ERP 系統
*/
export async function login(page: Page, username = 'mama', password = 'mama9453') {
await page.goto('/');
await page.fill('#username', username);
await page.fill('#password', password);
await page.getByRole('button', { name: '登入系統' }).click();
// 等待儀表板載入完成
await page.waitForSelector('text=系統概況', { timeout: 10000 });
}
3.2 使用方式
import { login } from './helpers/auth';
test('應顯示庫存清單', async ({ page }) => {
await login(page);
await page.goto('/inventory/stock-query');
// ...斷言
});
4. 測試撰寫規範
4.1 測試結構模板
import { test, expect } from '@playwright/test';
import { login } from './helpers/auth';
test.describe('模組功能名稱', () => {
// 若整個 describe 都需要登入,使用 beforeEach
test.beforeEach(async ({ page }) => {
await login(page);
});
test('應正確顯示頁面標題與關鍵元素', async ({ page }) => {
await page.goto('/target-page');
// 驗證頁面標題
await expect(page.getByText('頁面標題')).toBeVisible();
// 驗證表格存在
await expect(page.locator('table')).toBeVisible();
});
test('應能執行 CRUD 操作', async ({ page }) => {
// ...
});
});
4.2 斷言 (Assertions) 慣例
| 場景 | 優先使用 | 避免使用 |
|---|---|---|
| 驗證頁面載入 | page.getByText('關鍵文字') |
page.waitForURL() ※ |
| 驗證元素存在 | expect(locator).toBeVisible() |
.count() > 0 |
| 驗證表格資料 | page.locator('table tbody tr') |
硬編碼行數 |
| 等待操作完成 | expect().toBeVisible({ timeout }) |
page.waitForTimeout() |
Note
※ Star ERP 使用 Inertia.js,頁面導航不一定改變 URL(例如儀表板路由為
/)。 因此優先使用頁面內容驗證,而非依賴 URL 變化。
4.3 選擇器優先順序
依照 Playwright 官方建議,選擇器優先順序為:
- Role —
page.getByRole('button', { name: '登入系統' }) - Text —
page.getByText('系統概況') - Label —
page.getByLabel('帳號') - Placeholder —
page.getByPlaceholder('請輸入...') - Test ID —
page.getByTestId('submit-btn')(需在元件加data-testid) - CSS —
page.locator('#username')(最後手段)
4.4 禁止事項
// ❌ 禁止:硬等待(不可預期的等待時間)
await page.waitForTimeout(5000);
// ✅ 正確:等待特定條件
await expect(page.getByText('操作成功')).toBeVisible({ timeout: 5000 });
// ❌ 禁止:在測試中寫死測試資料的 ID
await page.goto('/products/42/edit');
// ✅ 正確:從頁面互動導航
await page.locator('table tbody tr').first().getByRole('button', { name: '編輯' }).click();
5. 截圖與視覺回歸
5.1 手動截圖(文件用途)
// 成功截圖存於 e2e/screenshots/
await page.screenshot({
path: 'e2e/screenshots/inventory-list.png',
fullPage: true,
});
5.2 視覺回歸測試(偵測 UI 變化)
test('庫存頁面 UI 應保持一致', async ({ page }) => {
await login(page);
await page.goto('/inventory/stock-query');
// 比對截圖,pixel 級差異會報錯
await expect(page).toHaveScreenshot('stock-query.png', {
maxDiffPixelRatio: 0.01, // 容許 1% 差異(動態資料)
});
});
Note
首次執行
toHaveScreenshot()會自動建立基準截圖。 後續執行會與基準比對,更新基準用:npx playwright test --update-snapshots
6. 執行指令速查
# 執行所有 E2E 測試
npx playwright test
# 執行特定模組測試
npx playwright test e2e/login.spec.ts
# UI 互動模式(可視化瀏覽器操作)
npx playwright test --ui
# 帶頭模式(顯示瀏覽器畫面)
npx playwright test --headed
# 產生 HTML 報告並開啟
npx playwright test --reporter=html
npx playwright show-report
# 更新視覺回歸基準截圖
npx playwright test --update-snapshots
# 只執行特定測試案例(用 -g 篩選名稱)
npx playwright test -g "登入"
# Debug 模式(逐步執行)
npx playwright test --debug
7. 開發檢核清單 (Checklist)
新增頁面或功能時:
- 是否已為新頁面建立對應的
.spec.ts測試檔? - 測試是否覆蓋主要的 Happy Path(正常操作流程)?
- 測試是否覆蓋關鍵的 Error Path(錯誤處理)?
- 共用的登入步驟是否使用
helpers/auth.ts? - 斷言是否優先使用頁面內容而非 URL?
- 選擇器是否遵循優先順序(Role > Text > Label > CSS)?
- 測試是否可獨立執行(不依賴其他測試的狀態)?
提交程式碼前:
- 全部 E2E 測試是否通過?(
npx playwright test) - 是否有遺留的
test.only或test.skip?