身份驗證狀態與視覺比對
多數應用程式的測試都需要先登入。如果每支測試都重新走一次登入流程,不只拖慢執行速度,登入頁本身若有變動還會讓大量不相關的測試一起失敗。Playwright 提供 Storage State 機制解決這個問題,這一頁也一併介紹另一個常見進階功能:視覺比對(Visual Comparisons)。
Storage State:儲存並重複使用登入狀態
先用一支獨立的「設定用測試」登入一次,把當下的 Cookies 與 LocalStorage 存成檔案:
// auth.setup.ts
import { test as setup } from '@playwright/test';
const authFile = 'playwright/.auth/user.json';
setup('登入並儲存狀態', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('帳號').fill('demo@vcdemy.com');
await page.getByLabel('密碼').fill('password123');
await page.getByRole('button', { name: '登入' }).click();
await page.waitForURL('/dashboard');
await page.context().storageState({ path: authFile });
});
在設定檔中,把這支測試設為其他測試的前置步驟(dependencies),並讓其他 project 直接載入已儲存的狀態:
export default defineConfig({
projects: [
{ name: 'setup', testMatch: /auth\.setup\.ts/ },
{
name: 'chromium',
use: { ...devices['Desktop Chrome'], storageState: 'playwright/.auth/user.json' },
dependencies: ['setup'],
},
],
});
之後所有屬於 chromium 這個 project 的測試,一開始就已經是登入狀態,不需要重複操作登入表單,執行速度更快,也讓登入流程本身可以獨立成一支測試單獨驗證。若需要測試「未登入」或「不同角色」的情境,可以另外建立不套用 storageState 的 project,或分別儲存不同角色的狀態檔案。
視覺比對(Visual Comparisons)
有些畫面錯誤(例如版面跑掉、樣式遺失)很難用一般斷言(檢查文字、屬性)偵測,這時可以用截圖比對:
test('首頁外觀應與基準截圖一致', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot('homepage.png');
});
第一次執行時,Playwright 會產生一張「基準截圖(baseline)」存到 __screenshots__ 資料夾;之後每次執行都會拿目前畫面與基準比對,若像素差異超過門檻(可用 maxDiffPixelRatio 調整),測試就會失敗,並在報表中並排顯示「預期畫面」「實際畫面」「差異標示」三張圖。
// 只比對特定區塊,避免動態內容(如時間、廣告輪播)造成誤判
await expect(page.getByTestId('product-card')).toHaveScreenshot('product-card.png');
視覺比對的注意事項
- 不同作業系統的字體渲染會有些微差異,官方建議在 CI 上統一用同一種環境(例如官方 Docker Image)產生與比對基準截圖,避免本機與 CI 結果不一致。
- 畫面若有時間、隨機內容,建議先用
mask選項遮蔽該區塊,或改用route.fulfill()(見 API 測試與請求攔截)固定測試資料,減少不必要的誤判。 - 視覺比對適合用在少數重要、版面複雜的頁面,不建議每個頁面都加,否則基準截圖維護成本會快速增加。
下一步
最後看 平行執行與 CI/CD 整合,了解如何加速測試執行,並整合進持續整合流程。