1. Vì sao flaky test là kẻ thù đắt nhất của đội QA
Flaky test là những test cho kết quả khi xanh khi đỏ dù mã nguồn không đổi và dữ liệu đầu vào không đổi. Nghe qua có vẻ vô hại, nhưng ở quy mô lớn chúng là thảm hoạ ngầm: mỗi lần đèn đỏ giả xuất hiện, một kỹ sư phải dừng lại điều tra, rồi chạy lại, rồi nghi ngờ. Tệ hơn, khi đội ngũ đã quen với 'chắc lại flaky thôi', họ bắt đầu bỏ qua đèn đỏ theo phản xạ — và đúng lúc đó một lỗi thật lọt qua cửa vì bị nhầm là flaky.
Chi phí của flaky không chỉ là thời gian. Nó bào mòn thứ quý nhất của một bộ test tự động: niềm tin. Một suite mà đội ngũ không còn tin thì dù có mười nghìn test cũng vô dụng, vì không ai dám dựa vào nó để quyết định release. Ở các domain nhạy cảm như fintech, mất niềm tin vào test đồng nghĩa với việc hoặc bạn chặn release quá đà (làm chậm sản phẩm), hoặc bạn thả lỏng và để rủi ro mất tiền lọt qua. Cả hai đều đắt.
Bài này không dừng ở việc 'giảm flaky' như một mẹo kỹ thuật. Nó bàn cách dùng AI để chống flaky ở quy mô lớn mà vẫn giữ được ý nghĩa của một test 'xanh'. Đó là chỗ nhiều đội ngũ sa bẫy: họ giảm flaky bằng cách retry hoặc nới lỏng assertion, rồi vui mừng vì bảng đã xanh — nhưng đã vô tình che mất bug thật. Nguyên tắc xuyên suốt: dùng AI để phân loại và sửa vấn đề của test, tuyệt đối không dùng nó để làm mờ oracle nghiệp vụ.
2. Bốn nguồn gốc flaky: timing, thứ tự, state chung, mạng
Không thể sửa flaky nếu không phân loại đúng nguyên nhân. Kinh nghiệm cho thấy đại đa số ca flaky rơi vào bốn nhóm gốc. Nhóm timing: test kiểm tra một trạng thái trước khi ứng dụng kịp cập nhật, thường do dùng sleep cứng hoặc chờ sai điều kiện. Nhóm thứ tự (order dependence): test B chỉ xanh nếu test A chạy trước, vì A để lại dữ liệu mà B ngầm dựa vào. Nhóm state chung: nhiều test dùng chung một bản ghi trong DB hoặc cache và giẫm chân nhau khi chạy song song. Nhóm mạng: phụ thuộc dịch vụ ngoài chập chờn, timeout, hoặc mã lỗi 5xx thoáng qua.
- Timing: dấu hiệu là 'thêm sleep thì xanh'. Cách sửa: dùng auto-wait/expect có polling, không sleep cứng.
- Order dependence: dấu hiệu là 'đổi thứ tự chạy thì đỏ'. Cách sửa: mỗi test tự dựng và dọn dữ liệu, không dựa vào test khác.
- Shared state: dấu hiệu là 'chạy song song thì đỏ, chạy đơn thì xanh'. Cách sửa: cô lập dữ liệu theo test (tenant/worker riêng).
- Network: dấu hiệu là 'đỏ ngẫu nhiên ở bước gọi API ngoài'. Cách sửa: mock/route hoá dịch vụ ngoài, chỉ để mạng thật ở test tích hợp có chủ đích.
Việc phân loại này quan trọng vì mỗi nhóm có cách chữa khác nhau, và nếu chữa sai nhóm bạn chỉ giấu triệu chứng chứ không diệt nguyên nhân. Ví dụ đắt giá nhất là 'chữa' flaky timing bằng cách tăng số lần retry: bề mặt thì xanh hơn, nhưng nguyên nhân race condition vẫn còn, và một ngày nào đó nó biểu hiện trong production nơi không có retry cứu bạn.
3. Auto-waiting: xoá bỏ sleep cứng và race condition
Nguồn flaky phổ biến nhất là chờ sai. Người mới hay thêm sleep cứng kiểu 'đợi 2 giây rồi kiểm', nhưng 2 giây khi thì thừa (làm test chậm), khi thì thiếu (làm test đỏ giả). Cách đúng là chờ theo điều kiện: đợi cho tới khi phần tử đạt trạng thái mong muốn, với cơ chế polling và timeout hợp lý. Playwright và các công cụ hiện đại tích hợp auto-wait vào cả hành động lẫn assertion, nên nếu bạn dùng đúng API thì phần lớn timing flaky biến mất.
// SAI: sleep cứng — khi thừa khi thiếu, nguồn flaky timing kinh điển
await page.waitForTimeout(2000);
expect(await page.locator('#balance').innerText()).toBe('1.000.000');
// ĐÚNG: assertion có auto-wait + polling, chờ tới khi đạt trạng thái
await expect(page.getByTestId('balance')).toHaveText('1.000.000', { timeout: 10_000 });
// ĐÚNG: chờ điều kiện nghiệp vụ, không chờ thời gian
await expect
.poll(async () => (await api.get('/orders/O1')).data.status, { timeout: 15_000 })
.toBe('SETTLED');Một chi tiết dễ bỏ qua: hãy chờ đúng tín hiệu thể hiện việc đã hoàn tất, chứ không phải một tín hiệu trung gian. Ví dụ trong luồng thanh toán, đừng chờ 'spinner biến mất' rồi kiểm số dư — spinner có thể biến mất trước khi backend ghi sổ xong. Thay vào đó, hãy chờ chính trạng thái nghiệp vụ cuối cùng (đơn chuyển sang SETTLED, số dư cập nhật đúng). Chờ đúng tín hiệu vừa diệt flaky vừa làm assertion của bạn ý nghĩa hơn.
💬 Bình luận (0)
Chưa có bình luận nào. Hãy là người đầu tiên!