Product Management
Đăng nhập
ESC

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

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

Bài 40 — Smoke, Sanity, Regression, Confirmation Test

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

Nếu bạn hỏi mười QA engineer câu "Smoke test và Sanity test khác nhau chỗ nào?", nhiều khả năng bạn sẽ nhận về mười câu trả lời hơi khác nhau, và vài câu trong đó lẫn lộn hai khái niệm. Đây là một trong những chỗ mà thuật ngữ QA bị dùng lỏng lẻo nhất trong thực tế. Kết quả là gì? Đội test cãi nhau vô nghĩa trong retro, release manager không biết "smoke pass" nghĩa là được deploy hay chưa, và người mới vào team thì gọi mọi lần chạy lại test đều là "regression" cho tiện.

Bốn loại kiểm thử trong bài này — Smoke, Sanity, Regression, Confirmation (Re-test) — không phải là bốn công cụ khác nhau. Chúng là bốn thời điểm và bốn mục đích khác nhau trong vòng đời của một bản build. Hiểu đúng bốn loại này giúp bạn thiết kế đúng "cửa kiểm soát" (gate) cho từng giai đoạn, tiết kiệm thời gian chạy test, và quan trọng nhất là truyền đạt trạng thái chất lượng một cách chính xác cho cả team. Với vai trò QA Lead, đây là ngôn ngữ nền tảng bạn phải chuẩn hóa cho cả đội, vì nếu không mọi cuộc trao đổi về "bản build này ổn chưa" đều mù mờ.

Bài này tập trung riêng vào định nghĩa, phân biệt và cách áp dụng đúng bốn loại kiểm thử này. Chúng ta sẽ không đi sâu vào kỹ thuật thiết kế test case (đã có Bài 41–42), cũng không bàn về automation framework (Bài 46). Ở đây, mục tiêu là: sau khi học xong, bạn có thể nhìn bất kỳ hoạt động test nào trong pipeline và gọi đúng tên nó, đặt đúng chỗ.

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

Cách dễ nhất để nhớ bốn loại này là gắn chúng với câu hỏi mà mỗi loại trả lời.

Smoke test — "Bản build này có sống không?"

Tên gọi "smoke test" bắt nguồn từ ngành điện tử: cắm điện vào một mạch mới hàn, nếu nó bốc khói thì hỏng, khỏi cần test tiếp. Áp vào phần mềm, smoke test là bộ kiểm tra cực nhanh, cực nông, bao phủ các luồng sống còn nhất của hệ thống, chạy ngay sau khi có build mới để trả lời một câu duy nhất: "Bản build này có đủ ổn định để đưa vào test sâu hơn không?"

Đặc điểm của smoke test:

  • Thời lượng ngắn: thường 5–15 phút. Nếu smoke test của bạn mất một tiếng, nó không còn là smoke test nữa.
  • Bao phủ đường xương sống (critical path): khoảng 10–20 luồng quan trọng nhất — đăng nhập được không, trang chủ load không, đặt hàng/thanh toán có chạy không, API health-check có trả 200 không.
  • Nông chứ không sâu: chỉ kiểm tra "chức năng có chạy" (breadth), không kiểm tra biên, không kiểm tra edge case.
  • Chạy thường xuyên: sau mỗi lần deploy vào môi trường test/staging, và thường được tự động hóa trong CI/CD.
  • Là một cửa chặn (gate): smoke fail thì từ chối nhận build, trả ngược lại cho dev, không tốn công QA test tiếp.
Smoke test thường được viết sẵn thành một bộ cố định, có thể tự động hóa hoàn toàn, và không phụ thuộc vào nội dung của release cụ thể.

Sanity test — "Phần vừa sửa/thêm có hoạt động hợp lý không?"

Sanity test hẹp và sâu hơn smoke một chút. Sau khi một build đã qua smoke, hoặc sau khi dev vừa fix một bug/thêm một chức năng nhỏ, sanity test kiểm tra cụ thể phần vừa thay đổi có hành xử hợp lý (sane) không trước khi bỏ công test toàn diện. Nó trả lời: "Cái vừa sửa có đáng để tôi test tiếp không, hay lại sai ngay từ đầu?"

Đặc điểm:

  • Hẹp và tập trung: chỉ nhắm vào vài chức năng vừa thay đổi, không trải rộng cả hệ thống.
  • Sâu hơn smoke một chút: kiểm tra logic của phần đó có đúng không, chứ không chỉ "có chạy".
  • Thường thủ công và ad-hoc: ít khi được viết thành bộ cố định, vì nó phụ thuộc vào nội dung release.
  • Là gate cho phần cụ thể: sanity fail thì trả build về, khỏi cần test regression đầy đủ.
Điểm dễ nhầm: nhiều tài liệu và nhiều team gộp smoke và sanity làm một. Cách phân biệt gọn nhất: Smoke = rộng và nông, kiểm tra "cả hệ thống có sống"; Sanity = hẹp và sâu, kiểm tra "phần vừa đụng vào có tỉnh táo".

Regression test — "Thay đổi mới có làm hỏng cái cũ không?"

Regression testing kiểm tra rằng những chức năng đang chạy tốt không bị phá vỡ bởi thay đổi mới (code mới, fix bug, cấu hình mới, nâng cấp thư viện). Đây là loại test rộng nhất và tốn thời gian nhất, trả lời: "Tôi vừa thêm/sửa thứ này, liệu có làm hồi quy (regress) — tức làm hỏng — thứ gì đó đã hoạt động?"

Đặc điểm:

  • Rộng: có thể bao phủ toàn bộ hoặc một phần lớn hệ thống.
  • Tốn thời gian: là ứng cử viên số một cho tự động hóa, vì phải chạy đi chạy lại mỗi release.
  • Có thể chọn lọc: regression đầy đủ (full) chạy tất cả, hay regression chọn lọc (selective) chỉ chạy phần liên quan đến vùng thay đổi, tùy rủi ro và thời gian.
  • Chạy muộn hơn: sau khi smoke/sanity đã pass và chức năng mới đã được test.

Confirmation test (Re-test) — "Bug đã báo giờ sửa xong chưa?"

Confirmation test, còn gọi là Re-test, là việc chạy lại đúng test case đã từng fail để xác nhận bug đã được sửa. Nếu QA báo bug "nút Thanh toán không bấm được", dev fix, thì confirmation test là thao tác bấm lại đúng nút đó theo đúng các bước tái hiện để xác nhận nó đã chạy. Nó trả lời: "Cái lỗi tôi báo, giờ đã hết chưa?"

Điểm cực kỳ hay bị lẫn: Confirmation (Re-test) khác Regression.

  • Re-test: chạy lại test case đã fail, để xác nhận bug cụ thể đã hết.
  • Regression: chạy lại các test case đang pass, để đảm bảo bản fix không làm hỏng chỗ khác.
Trong thực tế, khi một bug được fix, bạn làm cả hai: re-test để xác nhận bug hết, rồi regression quanh vùng đó để đảm bảo fix không gây tác dụng phụ.

Bảng so sánh nhanh

LoạiCâu hỏi trả lờiPhạm viĐộ sâuKhi nào chạy
SmokeBuild có sống không?Rộng (critical path)NôngNgay sau mỗi build/deploy
SanityPhần vừa sửa có hợp lý không?HẹpVừaSau smoke, trước test đầy đủ
RegressionCái mới có làm hỏng cái cũ không?RộngSâuSau khi chức năng mới đã test
Confirmation (Re-test)Bug đã sửa xong chưa?Đúng test case đã failSâu vào bug đóKhi bug được báo fixed

Tình huống thực tế

Ví dụ 1 — Sàn thương mại điện tử "ShopViet" và cái gate 12 phút

ShopViet, một sàn TMĐT giả định ở TP.HCM với khoảng 300.000 đơn/ngày, deploy lên staging trung bình 6–8 lần/ngày. Trước đây, mỗi lần dev đẩy build, một bạn QA sẽ bắt đầu test tay từ đầu, và không hiếm lần sau 45 phút mới phát hiện ra rằng chính build đó bị lỗi cấu hình khiến trang chủ trả lỗi 500 — nghĩa là 45 phút test kia vô nghĩa.

QA Lead của ShopViet dựng một bộ smoke test tự động gồm 15 kịch bản: mở trang chủ, tìm kiếm sản phẩm, thêm vào giỏ, đăng nhập, checkout đến bước chọn thanh toán, gọi 4 API core (catalog, cart, order, payment health). Bộ này chạy trong CI ngay sau deploy, mất trung bình 12 phút. Quy tắc cứng: smoke đỏ thì build bị chặn, tự động trả về Slack channel của dev, QA không đụng vào.

Kết quả sau một quý: số lần QA "test nhầm build hỏng" giảm về gần 0, và thời gian trung bình phát hiện build lỗi giảm từ ~40 phút xuống 12 phút. Bài học: smoke test không phải để tìm bug tinh vi — nó để bảo vệ thời gian của QA khỏi những build không đáng test. Giá trị của nó nằm ở việc chạy nhanh và chặn sớm.

Ví dụ 2 — Fintech "PayNhanh" nhầm Re-test với Regression

PayNhanh (giả định), một ví điện tử, có quy trình: bug được fix thì QA chỉ "test lại cái bug đó", tick pass, đóng ticket. Một lần, dev fix bug "sai số dư sau khi hoàn tiền". QA re-test đúng kịch bản hoàn tiền — pass, đóng bug. Nhưng bản fix đã thay đổi cách làm tròn số ở tầng tính toán chung, khiến giao dịch chuyển tiền thông thường bị lệch 1 đồng trong một số trường hợp. Lỗi lọt lên production, và với fintech thì lệch số dư dù 1 đồng cũng là sự cố nghiêm trọng về đối soát.

Nguyên nhân gốc: đội chỉ làm confirmation test (xác nhận bug hoàn tiền đã hết) mà bỏ regression quanh module tính toán số dư. QA Lead sau đó bổ sung quy tắc: mỗi bug fix chạm vào "vùng nhạy cảm" (tính tiền, số dư, phân quyền) bắt buộc kèm một bộ regression tối thiểu của vùng đó, đã được đánh dấu sẵn trong test management tool. Bài học: re-test trả lời "bug hết chưa", regression trả lời "fix có phá gì không" — thiếu vế thứ hai là công thức phổ biến để bug quay lại từ cửa sau.

Ví dụ 3 — Startup SaaS và bộ regression "phình" ngoài tầm kiểm soát

Một startup SaaS B2B (khoảng 20 người, sản phẩm quản lý nhân sự) tự hào có bộ regression 2.400 test case tự động. Vấn đề: bộ này chạy mất 3 tiếng, nên team chỉ chạy nó vào ban đêm. Mỗi release lớn, họ phải chờ đến sáng hôm sau mới biết có gãy gì không, làm chậm nhịp phát hành.

QA Lead phân tầng lại: tách một bộ smoke 20 case chạy 8 phút (gate deploy), một bộ regression chọn lọc khoảng 300 case gắn tag theo module để chạy theo vùng thay đổi (mất ~25 phút), và giữ full regression 2.400 case cho nightly và trước release lớn. Nhờ đó, feedback cho một PR bình thường rút từ "sáng hôm sau" xuống dưới 30 phút. Bài học: không phải cứ chạy tất cả mọi lúc là tốt. Đúng loại test, đúng thời điểm, đúng phạm vi mới là chiến lược. Regression đầy đủ là tài sản quý, nhưng đặt sai chỗ nó thành nút thắt cổ chai.

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

Đây là cách bạn thiết lập bốn tầng test này cho một team, theo trình tự thực dụng.

  • Xác định critical path cho smoke. Ngồi với PO và dev, liệt kê 10–20 luồng mà nếu hỏng thì hệ thống coi như "chết" với người dùng (đăng nhập, luồng doanh thu chính, API core). Viết chúng thành các test case rõ ràng, ưu tiên tự động hóa.
  • Đặt smoke làm gate trong pipeline. Cấu hình CI/CD để smoke chạy ngay sau deploy vào môi trường test. Quy ước cứng: smoke fail = build bị từ chối, thông báo tự động về dev. Không ai được "test tiếp cho chắc" khi smoke đỏ.
  • Chuẩn hóa sanity như một checklist ngắn theo release. Với mỗi build đã qua smoke, dựa trên release note, QA liệt kê nhanh 3–7 điểm cần kiểm tra hợp lý ở phần vừa thay đổi. Đây là bước lọc trước khi đầu tư test sâu.
  • Xây thư viện regression có gắn tag. Đưa mọi test case ổn định vào test management tool, gắn tag theo module/vùng chức năng. Việc này cho phép bạn chạy regression chọn lọc theo vùng thay đổi thay vì luôn chạy full.
  • Thiết lập quy trình bug: Re-test rồi Regression. Khi dev báo "đã fix", QA re-test đúng các bước tái hiện trong bug ticket. Nếu pass, chạy tiếp bộ regression của vùng liên quan. Nếu fail, mở lại bug với bằng chứng.
  • Phân tầng thời điểm chạy. Smoke: mỗi deploy. Sanity: mỗi build trước khi test sâu. Regression chọn lọc: mỗi PR/feature. Full regression: nightly và trước release lớn.
  • Chuẩn hóa ngôn ngữ trong team. Viết một trang định nghĩa bốn loại này dán vào wiki team, và yêu cầu mọi người dùng đúng tên trong ticket, trong stand-up, trong retro. Đây là việc của QA Lead và nó tiết kiệm vô số hiểu lầm.

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

Lỗi 1 — Gộp smoke và sanity làm một rồi để nó phình to. Nhiều team gọi mọi thứ là "smoke" và dần dồn hết case vào đó, khiến "smoke" chạy 40 phút và mất tác dụng chặn sớm. Mẹo: đặt giới hạn thời gian cứng cho smoke (ví dụ tối đa 15 phút); case nào không lọt vào ngân sách này thì chuyển sang regression.

Lỗi 2 — Chỉ re-test mà quên regression. Như ví dụ PayNhanh: xác nhận bug hết nhưng không kiểm tra tác dụng phụ. Mẹo: gắn quy tắc "bug fix ở vùng nhạy cảm bắt buộc kèm regression vùng đó" ngay trong quy trình đóng bug.

Lỗi 3 — Gọi mọi lần chạy lại đều là "regression". Người mới hay gọi việc test lại một bug là "regression", làm sai lệch báo cáo. Mẹo: dạy team câu thần chú — "Re-test chạy lại cái đã fail; Regression chạy lại cái đang pass".

Lỗi 4 — Regression full mọi lúc. Chạy toàn bộ mỗi lần biến CI thành nút thắt. Mẹo: đầu tư vào tag/phân vùng để chạy regression chọn lọc theo rủi ro; để full regression cho nightly và pre-release.

Lỗi 5 — Smoke test không được coi là gate. Nếu smoke đỏ mà vẫn có người test tiếp, cả cơ chế mất ý nghĩa. Mẹo: tự động hóa việc chặn build và thông báo, để nó không phụ thuộc vào kỷ luật cá nhân.

Mẹo tổng quát: khi phân vân loại nào, hãy hỏi lại câu hỏi mà loại đó trả lời. "Build sống không?" → smoke. "Phần vừa sửa tỉnh táo không?" → sanity. "Fix có phá cái cũ không?" → regression. "Bug đã hết chưa?" → confirmation.

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

  • Phân loại thao tác. Với mỗi tình huống sau, gọi tên đúng loại test: (a) Sau khi deploy staging lúc 9h sáng, chạy 15 case core trước khi bắt đầu ngày làm việc. (b) Dev báo đã fix bug "xuất Excel bị lỗi font", bạn mở lại và xuất thử đúng file đó. (c) Sau khi thêm tính năng coupon, bạn kiểm tra lại toàn bộ luồng checkout cũ. (d) PO vừa yêu cầu đổi text nút, bạn nhìn nhanh xem nút còn bấm được và text đã đúng chưa.
  • Thiết kế bộ smoke. Chọn một ứng dụng bạn quen (ví dụ một app đặt đồ ăn). Liệt kê 10–15 luồng critical path xứng đáng nằm trong smoke test, và ước lượng tổng thời gian chạy. Giải thích vì sao bạn loại một số luồng ra.
  • Xây quy tắc bug fix. Viết một đoạn quy trình 4–5 dòng cho team, mô tả rõ khi một bug được đánh dấu "fixed" thì QA phải làm những bước gì, theo thứ tự nào, và điều kiện để đóng bug.
  • Phân tầng regression. Cho một bộ 1.000 test case tự động chạy mất 2 tiếng, hãy đề xuất cách phân thành smoke / regression chọn lọc / full regression, kèm thời điểm chạy mỗi tầng.

Tóm tắt

  • Smoke (rộng, nông, 5–15 phút): "Build có sống không?" — chạy sau mỗi deploy, là gate chặn build hỏng, ưu tiên tự động hóa.
  • Sanity (hẹp, vừa): "Phần vừa sửa có hợp lý không?" — lọc nhanh trước khi test sâu, thường thủ công và theo release.
  • Regression (rộng, sâu): "Cái mới có làm hỏng cái cũ không?" — tốn thời gian nhất, phân tầng full/chọn lọc, ứng cử viên số một cho automation.
  • Confirmation / Re-test (đúng case đã fail): "Bug đã hết chưa?" — chạy lại test case đã fail; khác regression (chạy lại case đang pass). Khi fix bug thì làm cả hai.
  • Bốn loại này khác nhau ở mục đích và thời điểm, không phải công cụ. Việc của QA Lead là chuẩn hóa ngôn ngữ này cho cả team, đặt đúng loại vào đúng chỗ trong pipeline, và giới hạn phạm vi mỗi loại để chúng chạy đúng vai trò của mình.
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