1. Vì sao runtime CI là nút thắt của tốc độ phát hành
Khi bộ test end-to-end lớn dần, thời gian chạy trở thành nút thắt trực tiếp của tốc độ phát hành. Một bộ ba nghìn test chạy tuần tự có thể mất bốn mươi phút; nhân với hàng trăm pull request mỗi ngày, đội ngũ phải chờ đợi liên tục và vòng phản hồi chậm lại rõ rệt. Chờ CI lâu còn kéo theo hệ quả tâm lý: lập trình viên chuyển việc khác, mất ngữ cảnh, và khi CI đỏ họ phải quay lại nhớ mình đã làm gì. Rút ngắn runtime vì thế không chỉ là tối ưu kỹ thuật mà là đầu tư vào năng suất cả tổ chức.
Playwright cung cấp hai trục song song hoá bổ sung nhau. Trục thứ nhất là chạy song song bên trong một máy qua nhiều worker process, tận dụng nhiều nhân CPU. Trục thứ hai là chia bộ test thành nhiều mảnh (shard) và trải chúng lên nhiều máy CI chạy đồng thời. Kết hợp hai trục, một bộ test bốn mươi phút có thể rút xuống dưới năm phút. Bài viết này đi từ fullyParallel và workers, qua sharding trên nhiều máy, gộp báo cáo blob, cân bằng shard, tới đánh đổi chi phí và tốc độ, cuối cùng là cấu hình GitHub Actions hoàn chỉnh.
2. fullyParallel: song song hoá đến từng test
Mặc định Playwright chạy song song ở mức file: các file khác nhau chạy trên các worker khác nhau, nhưng test trong cùng một file chạy tuần tự. Bật fullyParallel nâng độ hạt lên mức test: mọi test đều có thể chạy song song bất kể nằm trong file nào. Điều này khai thác tối đa số worker và thường là cải thiện lớn nhất. Nhưng nó cũng phơi bày ngay lập tức mọi phụ thuộc ẩn giữa các test — đó chính là lý do bài trước nhấn mạnh cô lập dữ liệu là điều kiện tiên quyết.
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
fullyParallel: true, // song song đến từng test
// dev để undefined (auto = số nhân/2); CI cố định để tất định
workers: process.env.CI ? 4 : undefined,
// chặn merge nếu ai đó vô tình để .only trong code
forbidOnly: !!process.env.CI,
});Một lưu ý tinh tế: fullyParallel không có nghĩa là mọi thứ phải song song. Nếu vài test bắt buộc chạy tuần tự — ví dụ thao tác trên một tài nguyên độc quyền — bạn có thể khai báo test.describe.serial cho nhóm đó. Nhưng hãy dùng thật tiết kiệm: mỗi nhóm serial là một điểm nghẽn cản việc mở rộng. Mục tiêu là tối đa hoá phần song song và co nhỏ phần tuần tự tới mức tối thiểu tuyệt đối.
3. Điều chỉnh số workers cho đúng
Số worker là số process chạy test song song trên một máy. Đặt quá thấp thì lãng phí CPU; đặt quá cao thì các process tranh CPU và bộ nhớ, gây chậm ngược và thậm chí flaky do đói tài nguyên. Quy tắc khởi điểm: đặt bằng số nhân CPU cho test nhẹ, hoặc số nhân chia hai cho test nặng nhiều trình duyệt. Trên CI, luôn cố định con số thay vì để auto, vì runner có thể báo số nhân khác nhau và bạn muốn kết quả tất định giữa các lần chạy.
# Đo để chọn workers: chạy thử vài mức, so tổng thời gian
npx playwright test --workers=2 # ~ baseline
npx playwright test --workers=4 # thường nhanh hơn rõ
npx playwright test --workers=8 # cẩn thận: có thể chậm ngược nếu đói RAM
# Xem thời gian từng test để phát hiện test 'nặng' kéo cả suite
npx playwright test --reporter=list --reporter=json❓ Tăng workers từ 4 lên 8 nhưng tổng thời gian không giảm, thậm chí tăng. Vì sao?
workersを4から8にしたが総時間が減らず、むしろ増加。なぜ?
4. Sharding: trải bộ test lên nhiều máy CI
Song song trong một máy có giới hạn cứng bởi số nhân và bộ nhớ của máy đó. Để vượt qua, ta chia bộ test thành nhiều mảnh và chạy mỗi mảnh trên một máy CI riêng, cùng lúc. Tham số --shard=k/n bảo Playwright chỉ chạy mảnh thứ k trong tổng n mảnh. Nếu bạn có bốn máy và chia thành bốn shard, mỗi máy chạy một phần tư số test song song với ba máy kia, và tổng thời gian gần như chia bốn. Đây là mở rộng ngang, mở khoá tốc độ mà một máy đơn không bao giờ đạt được.
💬 Bình luận (0)
Chưa có bình luận nào. Hãy là người đầu tiên!