CYBERSOFT
Đăng nhập

Chống flaky ở quy mô lớn bằng AI và oracle bất biến

Chuyên nâng caoFintechAI AgentDebug/TraceNâng caoKinh nghiệm
🗓 1 tháng trước22 phút đọc·👁 1,018 lượt xem👤 463 người đọc

Phân loại bốn nguồn gốc flaky, ổn định hoá bằng auto-wait/seed tất định/cô lập state/mock mạng, dùng AI cụm hoá và gợi ý sửa mà KHÔNG che bug thật, và giữ oracle bất biến (double-entry, idempotency) để một test 'xanh' thật sự có ý nghĩa. Kèm quarantine + retry với trace, chỉ số flaky, kịch bản fintech và góc phỏng vấn.

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ốn nguồn gốc của flaky test Timing race · chờ sai sleep cứng Order phụ thuộc thứ tự test rò rỉ Shared state DB/cache chung song song đụng Network timeout · 5xx DNS chập chờn Ổn định hoá: auto-wait · seed tất định cô lập state · mock/route mạng AI cụm lỗi → gợi ý sửa KHÔNG che bug thật · oracle gác cổng
Bốn nguồn gốc flaky và hướng ổn định hoá; AI cụm lỗi nhưng oracle gác cổng.

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ụ.

Đây là bài nâng cao. Nó giả định bạn đã biết locator, auto-wait và assertion cơ bản, và muốn vận hành ổn định ở quy mô hàng nghìn test.

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.

⚠️ Retry là thuốc giảm đau, không phải thuốc chữa. Nó che flaky nhưng không diệt nguyên nhân. Chỉ dùng retry sau khi đã phân loại và ổn định hoá gốc, và luôn kèm oracle bất biế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.

ts
// 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.

💡 Cấm dùng waitForTimeout trong lint rule của repo. Bắt buộc mọi 'chờ' phải là chờ theo điều kiện (expect có auto-wait hoặc expect.poll).
🔒

Nội dung bị khoá

Bạn đang xem bản xem trước. Đăng nhập để mở khoá toàn bộ bài viết và tất cả tài liệu Tester/QA.

Đã xem 24% nội dung
  • Đọc trọn vẹn mọi bài viết
  • Lưu bài & ghi chú cá nhân
  • Theo dõi tiến độ đã đọc
  • Luyện phỏng vấn, ISTQB, Mock
Đăng nhập để đọc tiếp

Chưa có mã? Lấy mã qua Fanpage / Zalo CyberSoft.

0

💬 Bình luận (0)

Bạn có thể đọc mọi bình luận. Đăng nhập để bình luận

Chưa có bình luận nào. Hãy là người đầu tiên!