Get in touch
or send us a question?
CONTACT

Flaky test: nguyên nhân & cách fix 🧪✨

Flaky test là kiểu test lúc pass lúc fail dù code sản phẩm không đổi. Hôm nay CI đỏ, bấm re-run lại xanh. Lâu dần, team nhìn fail rồi mặc định: “chắc flaky thôi” — nguy hiểm nhất là bug thật cũng bị bỏ qua.

Bài này sẽ đi từ: 🔍 nhận biết → 🧩 nguyên nhân → 🛠️ cách fix → ✅ checklist phòng tránh.


1) Flaky test là gì? 🤔

Flaky test = test cho kết quả không ổn định trên cùng một phiên bản code / cùng điều kiện logic.

📌 Ví dụ:

  • Chạy 10 lần: ✅✅❌✅✅❌✅✅✅❌

  • Local pass 💻 nhưng CI fail 🤖

  • Fail nhiều hơn khi chạy parallel ⚡

🎯 Tác hại:

  • ⏳ tốn thời gian điều tra & rerun

  • 🚫 làm CI “đỏ giả”, chặn pipeline

  • 🧠 giảm niềm tin vào automation

  • 😵 team “lờn cảnh báo”


2) Dấu hiệu nhận biết flaky test 🔍

Bạn nên nghi ngờ flaky nếu thấy:

  • 🔁 Re-run cùng commit nhưng kết quả khác nhau

  • 🧩 Chạy lẻ thì pass, chạy cả suite thì fail

  • ⚡ Fail nhiều hơn khi bật parallel

  • ⏱️ Fail kiểu: timeout / element not found / stale element / intercepted

  • 🕒 Fail theo thời điểm: gần nửa đêm, cuối tháng, giờ cao điểm


3) Nguyên nhân phổ biến (và cách nhận diện nhanh) 🧩

3.1 ⏱️ Timing / Async / Đồng bộ kém

Dấu hiệu

  • “element not found”, “timeout”, “expected X but got Y”

  • UI chưa render xong / API chưa trả về / animation chưa kết thúc

Gốc rễ

  • Test “chạy nhanh hơn app”

  • Dùng sleep() thay vì chờ điều kiện thật


3.2 🧼 Shared state / Data bẩn / Phụ thuộc thứ tự

Dấu hiệu

  • Test chạy chung fail, chạy riêng pass

  • Fail theo thứ tự chạy (order-dependent)

Gốc rễ

  • Dùng chung account, chung record, chung dữ liệu

  • Không cleanup sau test

  • DB/cache/config bị ảnh hưởng từ test trước


3.3 ⚡ Race condition / Parallel execution

Dấu hiệu

  • Fail tăng vọt khi bật parallel

  • Test tạo/xóa/sửa dữ liệu thường fail

Gốc rễ

  • Nhiều test cùng update 1 resource

  • Test A xóa dữ liệu khi test B đang dùng


3.4 🌐 Network / Third-party / Environment không ổn định

Dấu hiệu

  • Timeout, 5xx, DNS, rate limit

  • Fail theo giờ cao điểm hoặc theo region

Gốc rễ

  • Phụ thuộc service ngoài không kiểm soát

  • CI network chậm hơn local


3.5 🎯 Locator/UI không ổn định

Dấu hiệu

  • “stale element reference”, “element intercepted”

  • UI thay đổi layout nhẹ là test fail

Gốc rễ

  • Locator dựa vào index/text dynamic/CSS dễ đổi

  • Click khi element chưa “clickable”


3.6 🕒 Timezone / Time / Random (test không deterministic)

Dấu hiệu

  • Fail gần nửa đêm, DST, cuối tháng

  • Fail ở case lịch, hạn sử dụng, filter theo ngày

Gốc rễ

  • Dùng thời gian thật (now()) không freeze

  • Random không seed


4) Quy trình chẩn đoán flaky test (rất hiệu quả) 🔍🧠

4.1 Xác nhận flaky hay bug thật ✅/❌

  • Re-run cùng commit 5–10 lần

  • Nếu fail không ổn định → khả năng cao là flaky

  • Nếu fail 100% → nhiều khả năng là bug thật hoặc test sai logic

4.2 Khoanh vùng theo dấu hiệu 🧭

  • ⏱️ Timeout/element → timing/sync

  • 🧼 Duplicate/không tìm thấy data → shared state / data bẩn

  • ⚡ Fail khi parallel → race condition

  • 🕒 Fail theo ngày giờ → time/timezone

4.3 Thu thập “bằng chứng” 📸🧾

  • UI test: screenshot + video + console log

  • API test: request/response + status + timing

  • DB/Integration: dump state trước/sau test

  • CI: lưu artifact để so sánh giữa lần pass/fail

4.4 Reproduce tối giản 🧪

  • Chạy test đó độc lập

  • Chạy test đó + nhóm liên quan để tìm phụ thuộc thứ tự


5) Cách fix theo từng nhóm nguyên nhân 🛠️✅

5.1 Fix timing/async: “wait theo điều kiện”, không “wait theo thời gian” ⏱️

✅ Nên:

  • Chờ spinner biến mất

  • Chờ button enabled/clickable

  • Chờ text/state đúng (ví dụ status chuyển “Success”)

  • Chờ request hoàn tất (nếu framework hỗ trợ network wait)

❌ Tránh:

  • sleep(2) / Thread.sleep() “cho chắc” → chậm và vẫn flaky

🔍 Nguyên tắc: Chỉ chờ đúng thứ bạn cần để assert đúng.


5.2 Fix shared state: cô lập dữ liệu test 🧼

✅ Nên:

  • Tạo data riêng cho mỗi test (🆔 UUID/prefix theo build)

  • Cleanup sau test (teardown) hoặc rollback transaction

  • Nếu có thể: môi trường automation riêng, không share với dev/manual

📌 Công thức bền:

  • Given: tạo user/data unique

  • When: thao tác

  • Then: assert

  • Finally: cleanup


5.3 Fix race condition/parallel: làm test “parallel-safe” ⚡

✅ Nên:

  • Không dùng chung account/record

  • “Namespace hóa” dữ liệu theo build ID / worker ID

  • Tag nhóm test: @parallel-safe vs @serial

🧱 Nếu bắt buộc dùng tài nguyên chung:

  • Dùng lock/mutex (ở tầng test runner hoặc DB)

  • Hoặc chạy nhóm đó serial để đảm bảo ổn định


5.4 Fix network/third-party: giảm phụ thuộc bên ngoài 🌐

✅ Nên:

  • Mock/stub third-party (SMS/Email/Payment/Maps…)

  • Tăng timeout hợp lý trên CI (CI thường chậm)

  • Retry có kiểm soát cho lỗi transient (timeout/502/503)

⚠️ Lưu ý:

  • ♻️ Retry chỉ là “băng cá nhân”

  • Nếu test chỉ “xanh nhờ rerun”, suite vẫn đang bệnh


5.5 Fix UI/locator: chọn selector ổn định 🎯

✅ Nên:

  • Dùng data-testid / accessibilityId / automationId

  • Tránh locator theo index hoặc text dynamic

  • Click/typing chỉ khi element visible + enabled + không bị che

✨ Bonus:

  • Tắt animation trong test env (nếu làm được) để giảm “intercepted/stale”


5.6 Fix time/random: làm test deterministic 🕒

✅ Nên:

  • Freeze time hoặc inject clock (fake time)

  • Seed random cố định

  • Cố định timezone trên CI và environment test


6) “Chữa cháy” khi flaky đang phá CI 🚑🔥

Khi CI đỏ liên tục, ưu tiên là giữ pipeline chạy ổn trước:

  1. 🧯 Quarantine flaky tests (tạm tách khỏi gate bắt buộc)

  2. 📊 Đo flaky rate (fail 1/50 khác fail 10/50)

  3. 🎯 Fix test fail nhiều nhất trước (impact cao)

  4. ✅ Bỏ quarantine và theo dõi 1–2 tuần


7) Checklist chống flaky test ✅

  • ⛔ Không lạm dụng sleep()

  • 🔁 Luôn wait theo điều kiện thật

  • 🆔 Data unique + cleanup/rollback

  • 🔀 Không phụ thuộc thứ tự chạy

  • ⚡ Chia nhóm parallel-safe / serial

  • 🏷️ Locator có test-id ổn định

  • 📸 CI lưu log/screenshot/video/artifact

  • 👤 Có owner + deadline cho flaky ticket


Kết luận 🎯

Flaky test thường đến từ:
⏱️ đồng bộ kém + 🧼 data không cô lập + ⚡ parallel không an toàn + 🌐 môi trường không ổn định + 🕒 time/random không deterministic.

Chỉ cần bạn nhìn đúng dấu hiệu và fix đúng nhóm, test suite sẽ xanh ổn định và đáng tin hơn rất nhiều ✅