Wiki

← Tất cả bài wiki

TestInfo (Metadata của test đang chạy & đính kèm bằng chứng vào report)

automationplaywright

TestInfo là object Playwright truyền vào mỗi test chứa metadata về lần chạy hiện tại: title, file, project, retry số mấy, worker, thư mục output... Quan trọng nhất là testInfo.attach() — đính kèm file/log bất kỳ (payload API, ảnh tự chụp, log hệ thống) vào HTML report để debug mà không cần mở server.

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

  • Mỗi test khi chạy nhận một object testInfo (tham số thứ 2 sau fixtures) — test 'tự biết' nó đang ở đâu, project nào, retry lần mấy.
  • testInfo.outputPath('ten-file') trả đường dẫn trong test-results/<test>/ — chỗ an toàn để ghi file mà không đè lẫn nhau khi chạy parallel.
  • testInfo.attach() gắn attachment (text, JSON, ảnh, file) hiện thẳng trong HTML report — bằng chứng đi cùng kết quả test.
  • testInfo.annotations gắn chú thích hiện trên report (vd link Jira) — biến report thành tài liệu truy vết, không chỉ bảng pass/fail.

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

  • Metadata hay dùng: testInfo.title, titlePath, file, project.name, retry, workerIndex, status, expectedStatus, duration, errors.
  • Ghi file đúng chỗ: testInfo.outputPath('payload.json') → file nằm trong thư mục riêng của test, tự đính kèm report.
  • Attach trực tiếp: await testInfo.attach('api-response', { body: '...', contentType: 'application/json' }) hoặc { path: filePath } với file đã có.
  • Annotation: testInfo.annotations.push({ type: 'issue', description: 'HT-101' }) — hiện trên report, tiện trace test ↔ ticket.
  • Điều khiển runtime: testInfo.skip(dieuKien, 'lý do') skip ngay trong thân test, testInfo.slow() / testInfo.setTimeout() nới timeout — mạnh hơn test.skip() khai báo tĩnh.

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

  • Đính kèm response API + annotation vào report: ``ts import { test, expect } from '@playwright/test'; test('đặt hàng COD', async ({ page, request }, testInfo) => { // Link ticket hiện trên report testInfo.annotations.push({ type: 'issue', description: 'HT-101' }); const res = await request.post('/api/cart', { data: { sku: 'PW-01', qty: 1 }, }); const body = await res.json(); // Attach payload — dev mở report là xem được request/response await testInfo.attach('cart-api-response', { body: JSON.stringify(body, null, 2), contentType: 'application/json', }); await page.goto('/cart'); await expect(page.getByText('PW-01')).toBeVisible(); }); ``
  • Hành xử khác khi đang retry — attach thêm bằng chứng soi flaky: ``ts test('upload file', async ({ page }, testInfo) => { await page.goto('/upload'); // ... thao tác upload if (testInfo.retry > 0) { // Chỉ lần retry mới chụp thêm bằng chứng await testInfo.attach('retry-screenshot', { body: await page.screenshot({ fullPage: true }), contentType: 'image/png', }); } }); ``
  • Skip runtime theo điều kiện và dọn dẹp trong hook: ``ts test('tính năng chỉ có ở prod', async ({ page }, testInfo) => { testInfo.skip(!process.env.RUN_PROD_ONLY, 'Chỉ chạy khi có RUN_PROD_ONLY'); // ... }); test.afterEach(async ({ page }, testInfo) => { // Lúc này status đã chốt — attach log nếu fail if (testInfo.status !== testInfo.expectedStatus) { await testInfo.attach('failure-shot', { body: await page.screenshot(), contentType: 'image/png', }); } }); ``

Best practices & Khi nào dùng

  • Test nặng API: luôn attach request/response payload vào report — khi fail trên CI, dev đọc report là đủ, không cần reproduce môi trường.
  • Luôn ghi file qua testInfo.outputPath() thay vì hardcode ./screenshots/x.png — file đi kèm đúng test, parallel không đè nhau.
  • Dùng testInfo.retry để hành xử khác ở lần retry: attach thêm screenshot/log, hoặc bỏ qua cleanup để giữ hiện trường.
  • Chuẩn hoá annotation trong team (issue, docs, owner...) để filter và trace report dễ dàng.
  • Trong fixture tự viết cũng nhận được testInfo — attach log setup/teardown rất tiện debug lỗi xảy ra ngoài thân test.

Gotchas, So sánh & Lưu ý

  • testInfo chỉ tồn tại trong context test/hook/fixture — helper function bên ngoài muốn dùng phải truyền tay vào.
  • testInfo.status chỉ chốt sau khi test xong — muốn biết pass/fail thật thì đọc trong afterEach, đừng check trong thân test.
  • Attach body quá lớn (vài MB text) làm HTML report phình nặng — file lớn nên ghi ra outputPath rồi attach bằng { path }.
  • testInfo.skip() khác test.skip(): skip() chạy được runtime theo điều kiện (vd thiếu env, feature flag off) — linh hoạt hơn skip khai báo tĩnh.
  • Annotation type là chuỗi tuỳ ý — không chuẩn hoá sẽ loạn ('bug', 'issue', 'JIRA' lẫn lộn); thống nhất một vài type cố định ngay từ đầu.