Mục lục
Mục Tiêu Bài Học
Sau bài này, bạn sẽ:
- Hiểu blob reporter là gì và tại sao nó tồn tại trong hệ sinh thái Playwright.
- Biết cú pháp khai báo blob reporter trong
playwright.config.tsvà CLI. - Nắm các output options:
outputFile,outputDir,fileName. - Phân biệt blob reporter với HTML reporter — khi nào dùng cái nào.
- Xây dựng CI workflow GitHub Actions matrix: nhiều shard chạy song song, upload blob, merge report.
- Kết hợp nhiều reporter trong cùng một shard (blob + list).
- Tránh 4 pitfall phổ biến khi triển khai blob reporter trên CI.
Phạm vi bài: Bài này tập trung vào blob reporter — cấu hình, output, và CI pattern. Cơ chế sharding (--shard=N/M, phân phối test) đã được đào sâu ở bài 69. Deep dive lệnh merge-reports và các option merge thuộc bài 71.
Blob Reporter Là Gì?
Blob reporter là một built-in reporter của Playwright, được thiết kế với mục đích duy nhất: lưu toàn bộ kết quả test của một shard vào một file ZIP để sau đó merge với kết quả từ các shard khác.
Vấn đề blob reporter giải quyết: khi dùng sharding trên CI, mỗi CI job chạy một shard — tức là chỉ chạy một phần test suite. Nếu mỗi shard generate HTML report riêng, bạn có N HTML report rời rạc, không thể tổng hợp thành một view duy nhất. Blob reporter cung cấp trung gian: mỗi shard xuất một blob, sau đó một job merge tập hợp tất cả blob và generate một HTML report tổng hợp duy nhất.
Luồng dữ liệu với blob reporter:
Shard 1/4 → blob-1.zip ─┐
Shard 2/4 → blob-2.zip ─┤
Shard 3/4 → blob-3.zip ─┼─→ merge-reports → HTML report tổng
Shard 4/4 → blob-4.zip ─┘
Blob reporter được giới thiệu trong Playwright v1.37. Trước đó, để có report tổng hợp từ sharding, cần dùng external tool hoặc giải pháp custom.
Điểm quan trọng: blob file không phải end-user report. Người dùng không mở blob file để xem kết quả test. Blob là dữ liệu trung gian cho công cụ merge.
Cú Pháp Config
Dạng string đơn giản:
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
// Dùng blob trên CI, list khi dev local
reporter: process.env.CI ? 'blob' : 'list',
});
Đây là pattern được Playwright docs khuyến nghị: CI dùng blob để sau đó merge; local dùng list để xem output ngay trên terminal.
Dạng array với options:
export default defineConfig({
reporter: process.env.CI
? [['blob', { outputFile: 'blob-report/report.zip' }]]
: [['list']],
});
CLI override:
# Kết hợp sharding và blob reporter trực tiếp trên CLI
npx playwright test --shard=1/4 --reporter=blob
# Hoặc explicit với outputFile
npx playwright test --shard=2/4 --reporter=blob
Khi dùng CLI --reporter=blob, không thể truyền options như outputFile trực tiếp — cần khai báo trong config. CLI chỉ chọn reporter theo tên.
Output Options
Blob reporter có ba output options:
| Option | Default | Mô tả |
|---|---|---|
outputFile |
blob-report/<random>.zip |
Path đầy đủ đến file ZIP output. Khi set option này, outputDir và fileName bị bỏ qua. |
outputDir |
blob-report/ |
Folder chứa blob. Tên file vẫn random nếu không set fileName. |
fileName |
Random UUID string | Tên file cụ thể bên trong outputDir. |
Ví dụ các cách khai báo:
// Cách 1: outputFile — kiểm soát hoàn toàn path
reporter: [['blob', {
outputFile: 'reports/shard-1.zip',
}]]
// Cách 2: outputDir — chỉ đổi folder, tên file vẫn random
reporter: [['blob', {
outputDir: 'ci-reports/',
}]]
// Cách 3: outputDir + fileName — folder và tên cụ thể
reporter: [['blob', {
outputDir: 'ci-reports/',
fileName: 'shard-1.zip',
}]]
// Cách 4: không set gì — output vào blob-report/.zip
reporter: [['blob']]
Khi nào dùng random filename: Khi chạy nhiều shard trên cùng máy hoặc không muốn quản lý tên file thủ công. Tên random tránh ghi đè giữa các shard.
Khi nào dùng tên cụ thể: Khi muốn debug dễ hơn (biết blob nào của shard nào) hoặc khi CI workflow cần biết tên file để upload artifact theo tên cố định.
Blob Format — Cấu Trúc Bên Trong
Blob file là một ZIP archive chứa:
- Events stream — toàn bộ test events (test started, test ended, step started, attachment, etc.) được serialise theo schema internal của Playwright.
- Attachments — screenshot, video, trace file đính kèm từ các test thất bại hoặc được bật capture.
- Metadata — thông tin về shard: index, tổng shard, Playwright version, timestamp.
Schema của blob file là internal Playwright format — không có tài liệu public và có thể thay đổi giữa các minor version. Đây là lý do blob version mismatch giữa các Playwright version khác nhau sẽ gây lỗi khi merge (pitfall ở mục 11).
Không nên parse blob thủ công. Công cụ hợp lệ duy nhất để đọc blob là npx playwright merge-reports. Nếu cần programmatic access vào test results, dùng JSON reporter thay thế.
File size: Blob file có thể lớn khi suite có nhiều test với trace/video/screenshot enabled. Mỗi attachment được nhúng vào ZIP — suite 500 test với trace enabled có thể tạo blob vài trăm MB per shard. Cần tính toán storage và CI artifact retention phù hợp.
So Sánh Với HTML Reporter
| Tiêu chí | Blob Reporter | HTML Reporter |
|---|---|---|
| Mục đích | Machine-readable, intermediate data | Human-readable, end-user view |
| Xem trực tiếp | Không — cần merge trước | Có — npx playwright show-report |
| Sharding support | Designed cho sharding, merge nhiều blob | Một report per run, không merge được native |
| File output | Một ZIP per shard | Folder playwright-report/ per run |
| Format | ZIP (binary, internal schema) | HTML + JS + assets |
| Khi dùng | CI sharding, cần report tổng sau merge | Local dev, CI không sharding |
Workflow khuyến nghị cho CI có sharding: dùng blob per shard, sau đó merge thành HTML report ở job cuối. Không nên dùng HTML reporter trực tiếp trên từng shard — bạn sẽ có N HTML report riêng biệt và không có cách hợp nhất chúng natively.
Shard job: blob reporter → *.zip
Merge job: merge-reports --reporter=html → HTML report tổng
Kết quả: một HTML report duy nhất chứa toàn bộ test của tất cả shard.
CI Workflow Pattern
Pattern chuẩn với GitHub Actions matrix — 4 shard chạy song song, sau đó merge report:
# .github/workflows/playwright.yml
name: Playwright Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false # shard khác tiếp tục chạy dù một shard fail
matrix:
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx playwright install --with-deps chromium
- name: Run shard ${{ matrix.shard }}/4
run: npx playwright test --shard=${{ matrix.shard }}/4 --reporter=blob
- name: Upload blob artifact
if: always() # upload dù test fail
uses: actions/upload-artifact@v4
with:
name: blob-${{ matrix.shard }}
path: blob-report/
retention-days: 1 # artifact ngắn hạn, chỉ cần qua job merge
merge:
needs: test
runs-on: ubuntu-latest
if: always() # merge dù một số shard fail
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx playwright install --with-deps chromium
- name: Download all blob artifacts
uses: actions/download-artifact@v4
with:
path: all-blobs/
pattern: blob-*
merge-multiple: true
- name: Merge reports
run: npx playwright merge-reports --reporter=html all-blobs/
- name: Upload HTML report
uses: actions/upload-artifact@v4
with:
name: playwright-html-report
path: playwright-report/
retention-days: 30
Điểm quan trọng trong workflow trên:
fail-fast: false— nếu một shard fail, các shard còn lại tiếp tục chạy. Nếu không set này, toàn bộ matrix bị cancel ngay khi shard đầu tiên fail, merge job không có đủ data.if: always()trên upload artifact — đảm bảo blob được upload dù test trong shard đó có lỗi.merge-multiple: true— download artifact từ nhiều job (blob-1, blob-2, blob-3, blob-4) vào cùng một folder.retention-days: 1cho blob — blob là dữ liệu trung gian, không cần giữ lâu. HTML report giữ 30 ngày để review sau.
Lệnh merge-reports và các option của nó sẽ được đào sâu ở bài 71.
Multiple Reporters Per Shard
Một shard có thể dùng nhiều reporter đồng thời. Ví dụ phổ biến: dùng blob để merge sau, đồng thời dùng list để xem output trên stdout trong CI log:
// playwright.config.ts
export default defineConfig({
reporter: process.env.CI
? [
['blob'], // lưu data cho merge
['list'], // in test name/status ra stdout — dễ scan CI log
]
: 'list', // local: chỉ cần list
});
Khi dùng line hoặc dot thay vì list — phù hợp hơn với CI log dài vì output ngắn gọn hơn:
reporter: process.env.CI
? [['blob'], ['line']] // line: một dòng per test, tiết kiệm log hơn list
: 'list',
Không nên dùng HTML reporter kết hợp với blob trên CI:
// Không cần thiết — HTML per shard rồi lại merge blob
reporter: process.env.CI
? [['blob'], ['html']] // html per shard bị lãng phí, sẽ bị replace bởi merged HTML
: 'list',
Nếu muốn xem HTML cho một shard cụ thể để debug, chạy lại shard đó local với --reporter=html thay vì tạo HTML trên CI cho mọi shard.
Unique Blob Filename Per Shard
Khi mỗi shard chạy trên CI job riêng biệt (matrix), tên file random vẫn an toàn vì các job có filesystem riêng. Tuy nhiên, đặt tên có nghĩa giúp debug khi cần xác định blob của shard nào bị vấn đề:
// playwright.config.ts
// SHARD_INDEX được set từ CI environment
export default defineConfig({
reporter: process.env.CI
? [['blob', {
outputFile: `blob-report/shard-${process.env.SHARD_INDEX}.zip`,
}]]
: 'list',
});
# Trong GitHub Actions — truyền SHARD_INDEX vào env
- name: Run shard ${{ matrix.shard }}/4
run: npx playwright test --shard=${{ matrix.shard }}/4
env:
SHARD_INDEX: ${{ matrix.shard }}
Output sẽ là blob-report/shard-1.zip, blob-report/shard-2.zip, v.v. Khi download artifact về local để debug, tên file cho biết ngay blob đó chứa kết quả của shard nào.
Nếu không cần debug, dùng random filename là đủ — merge-reports đọc tất cả *.zip trong folder mà không cần biết tên cụ thể.
Xem Blob Locally
Blob file không thể mở trực tiếp để xem. npx playwright show-report blob-report/shard-1.zip không hoạt động — show-report chỉ nhận folder HTML report, không nhận ZIP.
Để xem kết quả từ blob, phải merge trước:
# Merge một hoặc nhiều blob thành HTML report
npx playwright merge-reports --reporter=html blob-report/
# Sau đó mở report
npx playwright show-report
Điều này áp dụng ngay cả local — nếu bạn chạy một shard local với --reporter=blob và muốn xem kết quả, bạn phải chạy thêm bước merge.
Khi debug một shard local: Chạy lại shard đó với --reporter=html thay vì merge blob:
# Debug shard 2 local — dùng HTML reporter trực tiếp
npx playwright test --shard=2/4 --reporter=html
# Xem report ngay
npx playwright show-report
Cách này nhanh hơn khi debug vì không cần bước merge trung gian.
Pitfalls
Pitfall 1: Quên upload blob artifact → merge job không có data
Nếu bước upload-artifact bị thiếu hoặc chỉ chạy khi test pass (không có if: always()), merge job download về folder rỗng và báo lỗi. Đây là lỗi hay gặp nhất khi setup workflow mới.
# Sai: chỉ upload khi test pass
- uses: actions/upload-artifact@v4
with:
name: blob-${{ matrix.shard }}
path: blob-report/
# Đúng: luôn upload, kể cả khi test fail
- uses: actions/upload-artifact@v4
if: always()
with:
name: blob-${{ matrix.shard }}
path: blob-report/
Pitfall 2: Mix Playwright version cross shard → merge fail
Blob format là internal schema của Playwright. Nếu shard job và merge job dùng Playwright version khác nhau (ví dụ do npm ci resolve khác nhau, hoặc cache package lock cũ), merge-reports có thể báo lỗi schema mismatch hoặc generate report sai.
Giải pháp: pin Playwright version chính xác trong package.json ("@playwright/test": "1.49.0" thay vì "^1.49.0"), và đảm bảo tất cả CI job dùng cùng package-lock.json.
Pitfall 3: Blob tích lũy local không được cleanup
Mặc định blob được lưu vào blob-report/. Nếu chạy nhiều lần local và không xóa, folder tích lũy nhiều ZIP file. merge-reports đọc tất cả ZIP trong folder — nếu có blob cũ từ run trước, kết quả merge bị sai (bao gồm cả test result đã cũ).
# Cleanup trước khi chạy local
rm -rf blob-report/
npx playwright test --shard=1/2 --reporter=blob
Trên CI không bị vấn đề này vì mỗi job có filesystem sạch.
Pitfall 4: Dùng blob reporter khi không có sharding → confusing
Nếu config set reporter: 'blob' nhưng không chạy với --shard, Playwright vẫn tạo blob file bình thường — nhưng không có gì để merge, và bạn không xem được kết quả trực tiếp. Output terminal trống (blob không in ra stdout). Nếu chạy local mà vô tình có reporter: 'blob' (ví dụ quên set process.env.CI guard), sẽ không thấy test result đâu cả.
// Luôn guard blob reporter với CI check
reporter: process.env.CI ? 'blob' : 'list',
// Hoặc dùng multi-reporter với fallback visible
reporter: process.env.CI
? [['blob'], ['list']] // blob + list để vẫn thấy output
: 'list',
Quiz
Câu 1. CI workflow có 3 shard chạy song song, reporter là 'blob'. Shard 2 có 3 test fail. Điều gì xảy ra với blob artifact của shard 2 và với merge job?
Đáp án
Blob artifact vẫn được tạo bình thường — blob reporter ghi lại tất cả test results kể cả failed. Nếu workflow có if: always() trên upload artifact, blob được upload. Merge job nhận đủ 3 blob và tạo HTML report tổng, trong đó test fail của shard 2 hiển thị đầy đủ. Nếu thiếu if: always(), upload chỉ chạy khi shard pass — shard 2 fail → không upload → merge job thiếu data của shard 2.
Câu 2. Config khai báo reporter: [['blob', { outputFile: 'blob-report/shard-1.zip' }], ['list']]. Chạy npx playwright test --reporter=blob. Điều gì xảy ra?
Đáp án
CLI --reporter=blob override toàn bộ config reporter. Output chỉ dùng blob reporter, không có list reporter nữa. Và vì CLI không thể truyền options, blob dùng default output path (blob-report/<random>.zip), không phải blob-report/shard-1.zip đã khai báo trong config. Để giữ outputFile từ config, không được override bằng CLI — để config xử lý hoàn toàn.
Câu 3. Developer download blob artifact từ CI và chạy npx playwright show-report blob-report/shard-2.zip. Lệnh này có hoạt động không?
Đáp án
Không hoạt động. show-report nhận path đến folder chứa HTML report (folder playwright-report/ do HTML reporter tạo ra). Blob file ZIP không tương thích với show-report. Để xem kết quả từ blob, cần chạy npx playwright merge-reports --reporter=html blob-report/ trước, sau đó npx playwright show-report.
Câu 4. Suite có 200 test, chạy 4 shard với blob reporter, trace enabled cho tất cả test. Ước tính dung lượng cần lưu trữ artifact?
Đáp án
Mỗi shard chạy khoảng 50 test. Trace file cho một test thường 500 KB – 5 MB tuỳ theo độ phức tạp. Ước tính trung bình 1 MB per trace: 50 test × 1 MB = ~50 MB per shard, cộng overhead blob ZIP khoảng 10–20%. Tổng 4 blob: ~220–250 MB. Nếu test phức tạp (nhiều network request, video) có thể 500 MB – 2 GB tổng. Nên set retention-days: 1 hoặc 2 cho blob artifact để tránh chi phí storage lớn.
Câu 5. Merge job download xong artifact vào all-blobs/. Folder này chứa 4 file: report-a1b2c3.zip, report-d4e5f6.zip, report-g7h8i9.zip, report-j0k1l2.zip (tên random). Lệnh merge nào đúng?
Đáp án
npx playwright merge-reports --reporter=html all-blobs/. Lệnh merge-reports nhận đường dẫn đến folder chứa các blob ZIP, không cần liệt kê từng file. Nó tự đọc tất cả *.zip trong folder. Output mặc định là folder playwright-report/.
Bài Tiếp Theo
Bài 71: merge-reports CLI — Tổng Hợp Kết Quả Từ Nhiều Shard — đào sâu lệnh npx playwright merge-reports: các option reporter output, xử lý partial results khi một shard fail, và tích hợp vào CI pipeline.
