Wiki

← Tất cả bài wiki

Projects (multi-browser / multi-env trong playwright.config.ts)

automationplaywright

Project là một cấu hình chạy định nghĩa trong playwright.config.ts — mỗi project có browser, viewport, baseURL, grep và dependencies riêng, và cùng một test suite nhân ra chạy trên từng project. Nó giải quyết cross-browser testing, mobile emulation, multi-env và setup auth một lần — chọn lọc bằng --project.

Khái niệm & Bản chất

  • Project = một entry trong mảng projects của playwright.config.ts: gồm name, use (options riêng), testDir/testMatch/grep (chọn test), dependencies (project chạy trước).
  • Số lần chạy = số test × số project — 100 test trên 5 project = 500 lượt; mỗi cặp (test, project) là một kết quả riêng trên report.
  • Use case chính: cross-browser (Chromium/Firefox/WebKit), device emulation (mobile viewport), multi-env (dev/staging qua baseURL), phân nhóm (project smoke theo grep).
  • Dependencies: project 'setup' chạy trước (vd đăng nhập lưu storageState), các project khác khai báo dependencies: ['setup'] và reuse.
  • use của project merge lên use toàn cục — project chỉ cần khai báo phần khác biệt.

Cách hoạt động & API chính

  • Khai báo: projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }] — devices là preset sẵn của playwright.devices (viewport, userAgent, deviceScaleFactor...).
  • Chạy lọc CLI: npx playwright test --project=chromium, nhiều project: --project=chromium --project=firefox.
  • testMatch/testIgnore/grep/grepInvert trong project giới hạn test project đó pick — vd { name: 'smoke', grep: /@smoke/ }.
  • dependencies: ['setup'] — setup chạy trước, thường kèm testMatch: /.*\.setup\.ts/; setup fail → các project phụ thuộc bị skip.
  • use.storageState per project — mỗi project login dưới role khác nhau (admin vs user) với file state khác nhau.
  • Trong test đọc project hiện tại qua test.info().project.name hoặc fixture browserName, isMobile.

Ví dụ & Cú pháp thực tế

  • Config điển hình: setup auth 1 lần + multi-browser + mobile + project theo tag: ``ts // playwright.config.ts import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ use: { baseURL: process.env.BASE_URL ?? 'https://dev.hoctest.com', trace: 'on-first-retry', }, projects: [ // setup chạy trước — login 1 lần, lưu storageState { name: 'setup', testMatch: /auth\.setup\.ts/ }, { name: 'chromium', use: { ...devices['Desktop Chrome'], storageState: 'auth/user.json' }, dependencies: ['setup'], }, { name: 'firefox', use: { ...devices['Desktop Firefox'], storageState: 'auth/user.json' }, dependencies: ['setup'], }, { name: 'mobile-safari', use: { ...devices['iPhone 13'], storageState: 'auth/user.json' }, dependencies: ['setup'], }, // chỉ smoke test trên staging { name: 'staging-smoke', use: { baseURL: 'https://staging.hoctest.com' }, grep: /@smoke/, }, ], }); ``
  • File setup login dùng chung cho mọi project phụ thuộc: ``ts // auth.setup.ts — khớp testMatch của project 'setup' import { test as setup, expect } from '@playwright/test'; setup('đăng nhập và lưu state', async ({ page }) => { await page.goto('/login'); await page.getByLabel('Email').fill('qa@hoctest.com'); await page.getByLabel('Mật khẩu').fill('secret123'); await page.getByRole('button', { name: 'Đăng nhập' }).click(); await expect(page).toHaveURL(/dashboard/); await page.context().storageState({ path: 'auth/user.json' }); }); ``
  • Chạy lọc theo project: ``bash npx playwright test --project=chromium # 1 project npx playwright test --project=chromium --project=firefox npx playwright test --project=staging-smoke # smoke trên staging ``
  • Hai role trong cùng suite — mỗi role một project + storageState riêng: ``ts { name: 'admin', use: { ...devices['Desktop Chrome'], storageState: 'auth/admin.json' }, grep: /@admin/, }, { name: 'customer', use: { ...devices['Desktop Chrome'], storageState: 'auth/customer.json' }, grep: /@customer/, }, ``

Best practices & Khi nào dùng

  • Chia project theo một trục rõ ràng (browser, env, viewport, role) — tránh project 'kitchen-sink' gộp mọi thứ khó maintain.
  • Setup project + dependencies cho auth là pattern chính thức của Playwright — login 1 lần, mọi test reuse storageState, nhanh hơn login UI từng test rất nhiều.
  • CI theo tầng: PR/push chạy --project=chromium (hoặc project smoke), nightly chạy all project — tiết kiệm phút build mà vẫn cover cross-browser định kỳ.
  • Dùng grep/grepInvert trong project thay vì CLI flag dài — vd project stable với grepInvert: /@flaky/.
  • Env linh hoạt hơn bằng biến môi trường (baseURL: process.env.BASE_URL) kết hợp project — cùng project chromium chạy dev/staging tuỳ CI job.

Gotchas, So sánh & Lưu ý

  • Nhân bản số lần chạy — 5 project × 200 test = 1000 lượt; không phải test nào cũng cần cross-browser, dùng grep trong project hoặc test.skip(browserName !== ...) để cắt bớt.
  • Dependency project fail → mọi project phụ thuộc bị skip — setup auth hỏng thì cả suite im lặng; monitor project 'setup' riêng.
  • storageState phải tồn tại trước khi test chạy — quên dependencies thì test chạy với session trống (như chưa login) và fail khó hiểu.
  • Tên device preset gắn sẵn defaultBrowserType đúng (Desktop Safari → webkit, iPhone → webkit) — tự override sai browser sẽ lệch UA/viewport.
  • So sánh với matrix CI (GitHub Actions matrix browser): projects gọn hơn, chạy đủ browser trong 1 job, report gộp chung — matrix tách job song song hoá máy chủ nhưng setup lặp lại.
  • isMobile/browserName trong use ảnh hưởng test skip có điều kiện — kiểm tra preset device kỹ, vd iPad là isMobile: true còn Desktop thì false.