Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Test Analytics & Flaky Test Detection

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn là QA lead của một startup fintech ở TP.HCM. Mỗi sáng, đội của bạn chạy 2.400 test tự động trước khi deploy. Suite chạy mất 40 phút, và cứ mỗi lần chạy lại có 15–20 test "đỏ" một cách ngẫu nhiên — chạy lại thì lại xanh. Dev bắt đầu mất niềm tin: "Ôi test lại flaky đấy, cứ retry đi". Rồi một ngày, một test thật sự phát hiện bug thanh toán bị double-charge, nhưng nó bị chìm nghỉm giữa đám flaky, không ai để ý. Bug đó lên production, khách hàng bị trừ tiền hai lần.

Đây là câu chuyện xảy ra ở gần như mọi đội automation trưởng thành. Khi số lượng test vượt qua vài trăm, bạn không còn quản lý được suite bằng cảm tính nữa. Bạn cần dữ liệu về chính bộ test của mình — đó chính là Test Analytics. Và trong đó, việc phát hiện flaky test (test không ổn định) là kỹ năng sống còn, vì flaky test là "kẻ giết niềm tin" số một đối với automation.

Bài học này dạy bạn cách biến suite test từ một "hộp đen" thành một hệ thống có thể đo lường, theo dõi xu hướng, và tự động phát hiện những test đang mục ruỗng. Đây là tư duy của một SDET trưởng thành: bạn không chỉ viết test, bạn vận hành test như một sản phẩm có sức khỏe cần được giám sát.

Khái niệm cốt lõi

Test Analytics là gì?

Test Analytics là việc thu thập, lưu trữ và phân tích metadata của các lần chạy test theo thời gian — chứ không phải kết quả pass/fail của một lần chạy đơn lẻ. Mỗi lần suite chạy, bạn có một kho dữ liệu: test nào chạy, mất bao lâu, pass hay fail, chạy trên môi trường nào, commit nào, ai trigger. Khi bạn tích lũy dữ liệu này qua hàng trăm lần chạy, các xu hướng (trend) mới lộ ra — và xu hướng mới là thứ giúp bạn ra quyết định.

Một lần chạy đơn lẻ chỉ cho bạn biết "hôm nay hỏng ở đâu". Analytics cho bạn biết "suite của tôi đang khỏe lên hay yếu đi".

Ba metric quan trọng nhất cần track

1. Pass rate trend (xu hướng tỷ lệ pass)

Pass rate là phần trăm test pass trên tổng số test chạy. Nhưng con số một ngày không có ý nghĩa — bạn cần đường xu hướng. Nếu pass rate tuần này là 96%, tuần trước 98%, tuần trước nữa 99% — bạn đang có một suite đang xuống dốc. Điều quan trọng: hãy phân biệt pass rate của lần chạy đầu tiên (first-run pass rate) với pass rate sau khi retry. Nhiều đội tự lừa mình bằng cách nhìn con số "sau retry" luôn đẹp, trong khi first-run pass rate mới phản ánh sức khỏe thật.

2. Test duration trend (xu hướng thời gian chạy)

Suite của bạn có đang chậm dần không? Đây là câu hỏi bị bỏ quên nhiều nhất. Một suite khởi đầu 8 phút, sau một năm phình lên 35 phút — không phải vì có nhiều test hơn tương xứng, mà vì các test cũ ngày càng ì ạch (thêm sleep, wait dư thừa, setup nặng). Bạn cần track duration ở hai cấp:

  • Tổng thời gian suite (ảnh hưởng trực tiếp đến tốc độ feedback cho dev).
  • Duration từng test (để tìm "top 10 test chậm nhất" — thường 20% test tiêu tốn 80% thời gian).
3. Flaky rate (tỷ lệ test không ổn định)

Đây là ngôi sao của bài học. Định nghĩa chuẩn: một test là flaky nếu, với cùng một commit code không đổi, nó cho ra kết quả khác nhau (lúc pass lúc fail) một cách không xác định. Chữ "code không đổi" là mấu chốt — nếu test fail vì code thực sự có bug thì đó là true failure, không phải flaky.

Flaky rate thường tính bằng: số test có kết quả không nhất quán / tổng số test, trong một khoảng thời gian. Hoặc ở cấp độ lần chạy: số lần chạy bị "nhiễu" bởi flaky / tổng số lần chạy.

Vì sao flaky test cực kỳ nguy hiểm?

Flaky test gây ra hai thiệt hại nặng, và cả hai đều về mặt con người, không chỉ kỹ thuật:

  • Bào mòn niềm tin (alert fatigue). Khi dev thấy test đỏ mà biết "chắc lại flaky", họ sẽ retry một cách máy móc. Đến lúc có bug thật, họ vẫn retry — và bug lọt lưới. Test suite mất đi giá trị cốt lõi: làm "chuông báo cháy" đáng tin.
  • Lãng phí thời gian và tiền. Mỗi lần retry một suite 40 phút là 40 phút CI runner (tốn tiền cloud), cộng thời gian dev chờ đợi, cộng thời gian điều tra "ủa cái này flaky hay bug thật?".

Nguyên nhân gốc của flaky test

Để phát hiện và xử lý, bạn cần biết flaky test đến từ đâu. Các nhóm nguyên nhân phổ biến nhất:

  • Timing / race condition: test không chờ đúng cách (đây là lý do bài Wait Strategies quan trọng), UI chưa render xong đã assert.
  • Phụ thuộc thứ tự (test order dependency): test A vô tình để lại dữ liệu mà test B dựa vào; đổi thứ tự chạy là hỏng.
  • Dữ liệu chung / trạng thái chia sẻ: hai test cùng ghi vào một record trong DB, chạy song song thì đá nhau.
  • Phụ thuộc bên ngoài: gọi API thật, mạng chập chờn, thời gian hệ thống (test dựa vào ngày giờ hiện tại).
  • Môi trường: test chạy được trên máy dev nhưng flaky trên CI vì tài nguyên khác nhau.
Trong bài này ta tập trung vào việc phát hiện flaky qua analytics; cách sửa từng loại thuộc về Bài 28 (Flaky Test Management) và Bài 50 (Async Testing).

Tình huống thực tế

Tình huống 1: Sàn TMĐT phát hiện suite "âm thầm mục ruỗng"

Một công ty thương mại điện tử lớn ở Việt Nam (giả định gọi là ShopViet) có suite E2E 1.800 test chạy trên Jenkins. Trong sáu tháng, đội QA luôn báo cáo pass rate "sau retry" là 99,2% — nhìn rất đẹp, sếp yên tâm. Nhưng một QA mới vào dựng dashboard track first-run pass rate, và con số thật là 91%. Nghĩa là mỗi lần chạy, trung bình 160 test fail ở lần đầu rồi được retry cho xanh.

Khi phân tích sâu, họ thấy 47 test chiếm tới 80% các lần "fail-rồi-pass". Đó là những test flaky kinh niên đã bị che giấu bởi cơ chế retry tự động. Tệ hơn, có 3 lần trong sáu tháng, một bug thật đã bị retry-che-mất và lọt lên production.

Bài học: Cơ chế auto-retry là con dao hai lưỡi — nó giúp CI xanh nhưng giấu flaky rate thật. Luôn track first-run pass rate riêng biệt. Con số "đẹp sau retry" có thể là dấu hiệu nguy hiểm nhất.

Tình huống 2: Startup fintech và "top 10 test chậm nhất"

Một startup fintech ở Đông Nam Á (giả định gọi là PayNow) có suite API test tăng từ 12 phút lên 34 phút trong một năm. Dev than phiền vì mỗi PR phải chờ gần nửa tiếng. Thay vì viết lại toàn bộ, QA lead dùng test analytics: xuất duration từng test ra, sắp xếp giảm dần.

Kết quả: 8 test trong tổng số 900 chiếm 19 phút — hơn nửa thời gian suite. Điều tra thì ra chúng đều có Thread.sleep(5000) cứng để "chờ cho chắc", và một test gọi API bên thứ ba thật (không mock). Chỉ cần sửa 8 test này — thay sleep bằng polling, mock API ngoài — suite giảm còn 16 phút. Feedback cho dev nhanh gấp đôi mà không đụng tới 892 test còn lại.

Bài học: Đừng tối ưu mù. Analytics chỉ cho bạn đúng 20% test tiêu tốn 80% thời gian. Sửa đúng chỗ, hiệu quả gấp bội.

Tình huống 3: Đội mobile và flaky do chạy song song

Một đội QA làm app gọi xe dùng Appium chạy test song song trên 4 thiết bị để tiết kiệm thời gian. Sau khi bật parallel, flaky rate nhảy từ 2% lên 14%. Ban đầu họ đổ lỗi cho Appium.

Khi track flaky theo từng test và cross-reference với lịch chạy, họ phát hiện: các test flaky đều dùng chung một tài khoản test duy nhất. Khi 4 thiết bị cùng đăng nhập một tài khoản, phiên đăng nhập đá nhau. Giải pháp: cấp pool tài khoản riêng cho mỗi luồng song song. Flaky rate rớt về 2,5%.

Bài học: Flaky rate tăng vọt sau một thay đổi hạ tầng (bật parallel, đổi môi trường) là tín hiệu vàng. Analytics giúp bạn khoanh vùng: flaky theo test nào, xuất hiện từ mốc thời gian nào — từ đó truy ra nguyên nhân gốc thay vì đoán mò.

Hướng dẫn từng bước

Đây là quy trình thiết lập test analytics và phát hiện flaky test từ con số 0.

Bước 1 — Thu thập dữ liệu chuẩn hóa. Đảm bảo mọi lần chạy test đều xuất ra định dạng máy đọc được, phổ biến nhất là JUnit XML (hầu hết framework đều hỗ trợ export dạng này, kể cả pytest, JUnit, Cypress, Playwright). Mỗi record cần tối thiểu: tên test, kết quả, duration, timestamp, commit SHA, môi trường.

Bước 2 — Lưu trữ tập trung qua thời gian. Đừng để kết quả nằm rải rác trong log CI rồi bị xóa. Đẩy vào một nơi tích lũy được: một bảng trong database, hoặc dùng công cụ chuyên dụng như ReportPortal, Allure TestOps, Datadog Test Optimization, hoặc CI Analytics của chính GitHub/GitLab/CircleCI. Chìa khóa là dữ liệu phải sống qua nhiều lần chạy, mới vẽ được trend.

Bước 3 — Tính flaky bằng phương pháp cụ thể. Có ba cách thực dụng:

  • Re-run cùng commit: chạy lại (các) test fail trên đúng commit đó. Nếu lần sau pass → đánh dấu flaky. Nhiều CI có sẵn cờ như --rerun-fails hoặc plugin retry ghi lại được điều này.
  • Phân tích lịch sử: với mỗi test, nhìn N lần chạy gần nhất trên các commit khác nhau. Nếu kết quả nhảy pass/fail qua lại không tương quan với thay đổi code → nghi flaky.
  • Chạy định kỳ trên nhánh chính không đổi: đặt một job chạy suite nhiều lần liên tiếp trên cùng commit main mỗi đêm. Test nào không nhất quán chính là flaky "thuần khiết".
Bước 4 — Xây dashboard với các biểu đồ tối thiểu. First-run pass rate theo ngày/tuần; tổng duration suite theo thời gian; bảng "top 10 test chậm nhất"; bảng "top flaky offenders" (test flaky nhiều nhất). Đây là bốn góc nhìn đủ để vận hành một suite lành mạnh.

Bước 5 — Đặt ngưỡng cảnh báo và quy trình xử lý. Ví dụ: nếu một test flaky quá 3 lần trong 7 ngày → tự động gán nhãn @flaky và tạo issue giao cho người sở hữu. Nếu first-run pass rate tuần giảm dưới 95% → cảnh báo lên kênh QA. Analytics không có hành động đi kèm chỉ là biểu đồ để ngắm.

Bước 6 — Quyết định cách ly (quarantine). Với flaky kinh niên chưa sửa kịp, tách chúng ra một nhóm "quarantine" — vẫn chạy để theo dõi nhưng không làm đỏ pipeline chặn deploy. Điều này giữ tín hiệu CI sạch trong khi vẫn không "phủi" flaky dưới thảm. Kèm theo phải có time budget để dọn quarantine, kẻo nó thành bãi rác vĩnh viễn.

Lỗi thường gặp & mẹo

Lỗi 1 — Lạm dụng auto-retry để giấu vấn đề. Retry tự động rất tiện, nhưng nếu bạn retry mà không đo first-run pass rate, bạn đang tự bịt mắt. Mẹo: luôn ghi log riêng "test này pass nhờ retry lần thứ mấy", và coi mọi lần cần retry là một sự kiện flaky cần theo dõi.

Lỗi 2 — Nhầm true failure với flaky. Đánh dấu một bug thật là "flaky" rồi bỏ qua là thảm họa (nhớ ví dụ double-charge ở đầu bài). Mẹo: một test chỉ được coi là flaky khi bạn xác nhận nó pass/fail trên cùng commit. Nếu code đã đổi giữa hai lần chạy, đó chưa chắc là flaky.

Lỗi 3 — Track quá nhiều metric rồi không dùng cái nào. Dashboard 30 biểu đồ đẹp long lanh nhưng không ai nhìn. Mẹo: bắt đầu với đúng ba metric cốt lõi (first-run pass rate, duration trend, flaky rate). Thêm dần khi thực sự cần.

Lỗi 4 — Quên gắn context vào dữ liệu. Test fail mà không biết chạy trên môi trường nào, commit nào thì không điều tra được. Mẹo: luôn đính kèm commit SHA, branch, môi trường, và (với test UI) screenshot/video vào record.

Lỗi 5 — Xử lý flaky theo cảm tính thay vì theo số. "Tôi cảm thấy test login hay hỏng" không bằng "test login flaky 12/30 lần chạy tuần này". Mẹo: để dữ liệu xếp hạng ưu tiên — sửa flaky offender số 1 trước, nó thường giải quyết phần lớn nỗi đau.

Mẹo vàng — quy tắc "một tín hiệu sạch". Mục tiêu cuối cùng của test analytics là để khi CI báo đỏ, cả đội tin ngay rằng có gì đó thật sự hỏng. Mọi nỗ lực đo lường flaky đều phục vụ mục tiêu này: khôi phục niềm tin vào suite test.

Bài tập thực hành

  • Tính flaky rate thủ công. Lấy kết quả 20 lần chạy gần nhất của suite bạn (hoặc một project mẫu). Với mỗi test, đếm số lần pass và fail. Liệt kê những test có cả pass lẫn fail mà không tương quan với thay đổi code. Tính flaky rate = (số test flaky) / (tổng số test). Bạn sẽ bất ngờ với con số thật.
  • Tìm top 5 test chậm nhất. Xuất báo cáo duration (JUnit XML hoặc report của framework bạn dùng), sắp xếp giảm dần theo thời gian. Với mỗi test trong top 5, ghi giả thuyết vì sao nó chậm (sleep cứng? gọi API thật? setup nặng?).
  • Dựng dashboard tối thiểu. Dùng một Google Sheet đơn giản: mỗi hàng một lần chạy, các cột là ngày, tổng test, số pass lần đầu, số cần retry, tổng duration. Nhập tay 5 lần chạy và vẽ biểu đồ đường cho first-run pass rate. Cảm nhận sức mạnh của trend so với con số đơn lẻ.
  • Thiết kế quy tắc quarantine. Viết ra (bằng lời) chính sách của riêng bạn: điều kiện nào một test bị đưa vào quarantine, ai chịu trách nhiệm sửa, thời hạn bao lâu phải dọn. Đây là bài tập tư duy quy trình quan trọng như bài tập code.

Tóm tắt

Test Analytics biến bộ test của bạn từ hộp đen thành một hệ thống có sức khỏe đo lường được. Ba metric cốt lõi cần track theo xu hướng, không phải con số đơn lẻ: first-run pass rate (đừng để retry đánh lừa), test duration trend (suite có đang chậm dần?), và flaky rate (test lúc pass lúc fail trên cùng commit).

Flaky test nguy hiểm không phải vì nó "đỏ", mà vì nó bào mòn niềm tin và giấu bug thật — như câu chuyện double-charge ở đầu bài. Phát hiện flaky đòi hỏi dữ liệu tích lũy qua nhiều lần chạy, phương pháp xác định rõ ràng (re-run cùng commit, phân tích lịch sử, chạy định kỳ), và quan trọng nhất là hành động: gán nhãn, quarantine có kỷ luật, và có time budget để dọn dẹp.

Hãy nhớ mục tiêu cuối cùng: một tín hiệu sạch — để khi CI báo đỏ, cả đội tin ngay rằng có bug thật. Đó là lúc automation phát huy đúng giá trị của nó.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi