playwright.config.ts (File cấu hình trung tâm của test suite)
automationplaywright
playwright.config.ts là file cấu hình gốc điều khiển toàn bộ hành vi của test run: nơi tìm test, timeout, retry, số worker chạy song song, baseURL, các project trình duyệt, reporter và thư mục output. Nắm vững file này = kiểm soát được cách suite chạy trên cả local lẫn CI mà không cần sửa test.
Khái niệm & Bản chất
- Playwright Test tự đọc
playwright.config.ts(hoặc.js,.mjs) ở project root khi chạynpx playwright test; có thể chỉ định file khác bằng--config. - Export qua
defineConfig()— helper cung cấp type-check và autocomplete; bên trong là plain object nên có thể dùng biểu thức JS tuỳ ý. - Gần như mọi flag CLI đều có option tương ứng trong config (
--workers,--retries,--project...); flag CLI khi truyền sẽ override giá trị config. - Khối
usechứa options áp cho TẤT CẢ test (baseURL, trace, screenshot, viewport...); mỗiprojectcó thể khaiuseriêng để override — đây là cách chạy cùng test trên nhiều browser/device. process.envtrong config là cách chuẩn để một file config phục vụ nhiều môi trường:retries: process.env.CI ? 2 : 0,baseURL: process.env.BASE_URL.
Cách hoạt động & API chính
- Phạm vi test:
testDir(thư mục chứa spec),testMatch/testIgnore(glob lọc file). - Timeout:
timeout(mỗi test, mặc định 30s — gồm cả hook),expect.timeout(mỗi assertion, mặc định 5s),globalTimeout(toàn run). Override per test/file bằngtest.setTimeout(). - Song song:
workers(mặc định 50% số CPU),fullyParallel(cho phép song song cả các test trong CÙNG file — đòi hỏi test độc lập dữ liệu). - Ổn định CI:
retries(số lần chạy lại khi fail),forbidOnly(fail run nếu sóttest.only— bắt buộc bật trên CI),maxFailures(dừng sớm khi fail quá nhiều). - Artefact:
outputDir(nơi chứa trace/screenshot/video, MẶC ĐỊNH BỊ XOÁ SẠCH đầu mỗi run),preserveOutput(giữ artefact của test pass hay không),snapshotDir. webServer: tự khởi động dev server trước khi test và tắt sau khi xong —command,url/port,reuseExistingServer,timeout.
Ví dụ & Cú pháp thực tế
- Một config hoàn chỉnh, chạy được cả local lẫn CI:
``
ts import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ testDir: './tests', timeout: 30_000, // tối đa 30s mỗi test expect: { timeout: 5_000 }, // tối đa 5s mỗi assertion retries: process.env.CI ? 2 : 0, // CI retry 2 lần, local fail ngay workers: process.env.CI ? 4 : undefined,// CI giới hạn 4 worker fullyParallel: true, // song song cả test trong 1 file forbidOnly: !!process.env.CI, // cấm test.only lọt lên CI outputDir: 'test-results', reporter: [['html', { open: 'never' }], ['list']], use: { baseURL: process.env.BASE_URL ?? 'https://dev.hoctest.com', trace: 'on-first-retry', // chỉ ghi trace từ lần retry đầu screenshot: 'only-on-failure', video: 'retain-on-failure', }, projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, { name: 'webkit', use: { ...devices['Desktop Safari'] } }, { name: 'mobile', use: { ...devices['iPhone 13'] } }, ], webServer: { command: 'npm run dev', url: 'http://localhost:3000', reuseExistingServer: !process.env.CI, // local tái dùng server đang mở }, });`` - Override option cho một nhóm test mà không sửa config:
``
ts import { test, expect } from '@playwright/test'; test.use({ baseURL: 'https://staging.hoctest.com', locale: 'vi-VN' }); test.setTimeout(60_000); // nhóm này được 60s test.describe('checkout', () => { test('thanh toán thành công', async ({ page }) => { await page.goto('/cart'); // đi tới staging vì baseURL đã override }); });`` - Vài flag CLI hay dùng tương ứng với config:
``
bash npx playwright test --workers=1 # debug tuần tự npx playwright test --retries=1 --repeat-each=3 # bắt flaky npx playwright test --project=chromium # chỉ chạy 1 browser npx playwright test --grep "@smoke" # lọc theo tag trong title``
Best practices & Khi nào dùng
- Một config duy nhất, nhiều môi trường qua env var (
BASE_URL,CI) — đừng nhân bản file config cho từng env, sẽ nhanh lệch nhau. trace: 'on-first-retry'là sweet spot: local gần như không tốn dung lượng, còn CI vẫn có đủ bằng chứng để debug test fail/flaky.- Bật
fullyParallel: true+forbidOnlytrên CI để tận dụng CPU và chặntest.only— nhưng trước đó phải đảm bảo test không share data. - Giới hạn
workerstrên CI (4-8) vì runner CI yếu hơn máy dev; local đểundefinedcho Playwright tự tính. - Dùng
projects+devicespreset để cover browser/mobile thay vì tự khai viewport lung tung.
Gotchas, So sánh & Lưu ý
outputDirbị dọn sạch đầu mỗi run — đừng để script khác ghi file cần giữ vào đó; và artefact của test pass chỉ giữ nếupreserveOutputcho phép.timeouttính cảbeforeEach/beforeAllvào ngân sách của test đầu tiên — hook nặng có thể làm test "timeout" dù body chưa chạy.fullyParallellàm lộ mọi test phụ thuộc ngầm (ghi cùng user, cùng file): khi bật mà suite bắt đầu flaky thì vấn đề nằm ở test, không phải ở config.test.onlytrong code sẽ khiến CI fail nếuforbidOnlybật — đó là tính năng cứu người, không phải bug.webServer.reuseExistingServertiết kiệm vài giây mỗi run ở local, nhưng trên CI phải tắt để luôn chạy đúng code mới build.- Option trong
usecủa project merge (shallow) vớiuseglobal — muốn giữ setting global thì spread cả hai:use: { ...devices['iPhone 13'] }không tự merge baseURL nhưng các key khác vẫn kế thừa.
