AllianceProject Handbook
← Knowledge

Kiểm soát chất lượng

Smoke test và cách liệt kê case

Smoke test trả lời đúng một câu: bản build này có đáng để test tiếp không. Bài này cho bộ tiêu chí chọn case, công thức liệt kê từ chính kiến trúc app, và danh sách đề xuất cho ba module.

Cập nhật 14/09/2026chất lượngtestquality gate

10 phút

ngân sách cho cả suite

15 case

ngưỡng trên, không phải chỉ tiêu

100%

tỷ lệ pass bắt buộc

0

case được phép chập chờn

Smoke test trả lời câu gì

Tên gọi đến từ điện tử: cấp điện vào bảng mạch mới hàn, thấy khói thì rút điện mang đi sửa — không ai đo tiếp từng chân linh kiện. Smoke test giữ nguyên logic đó.

  1. Build ra

    CI dựng xong, artifact có sẵn

  2. Smoke suite

    10 phút, chạy trước mọi suite khác

  3. Xanh

    mở cửa cho functional, critical path, regression

  4. Đỏ

    trả build, không ai test tiếp

Vì nó là cổng đầu chuỗi, sai ở đây đắt hơn sai ở bất cứ suite nào khác: cổng quá chặt thì chặn oan cả ngày làm việc của đội test, cổng quá lỏng thì cả đội ngồi test một bản build đã chết.

Xanh nghĩa là gì, đỏ nghĩa là gì

Smoke xanh

  • Nghĩa là build cài được, mở được, các đường trục còn thông
  • Không nghĩa là tính năng làm đúng việc của nó
  • Không nghĩa là bản này release được
  • Nó chỉ mở cửa cho các suite sau chạy

Smoke đỏ

  • Dừng lại, trả build cho dev, ghi đúng một phiếu
  • Không mở hai mươi phiếu lẻ rồi test tiếp — mọi kết quả sau đó không đáng tin
  • Không "test tránh chỗ đang hỏng"
  • Không có ngoại lệ "đỏ này chấp nhận được"

Gạch cuối là ranh giới quan trọng nhất. Một case mà đội sẵn sàng bỏ qua khi nó đỏ là case thuộc regression suite, không thuộc smoke — để nó ở đây chỉ dạy cả đội thói quen phớt lờ màu đỏ.

Phân biệt với bốn suite sát cạnh

Năm suite dưới đây hay bị gọi lẫn tên nhau. Phân biệt bằng câu hỏi mỗi suite trả lời, đừng phân biệt bằng số lượng case.

Câu hỏi nó trả lời
Khi chạy
Đỏ thì làm gì
Smoke
Build này có đáng test tiếp không
Mỗi build
Trả build, dừng mọi suite sau
Sanity
Chỗ vừa sửa đã đúng chưa, vùng quanh nó còn nguyên không
Sau mỗi bug fix
Trả lại đúng bug đó cho dev
Critical path
Các luồng sinh ra giá trị của sản phẩm còn trọn vẹn không
Mỗi build và mỗi release
Chặn release
Functional
Tính năng này đúng đủ mọi nhánh của nó không
Khi làm xong tính năng
Phiếu bug cho tính năng đó
Regression
Thứ trước đây chạy được có còn chạy không
Trước release
Cân nhắc từng phiếu, chấp nhận được thì ghi lại

Sáu tiêu chí để một case được vào smoke suite

1.Câu hỏi chốt — case này đỏ thì còn test tiếp được gì không?

Trả lời được là "còn nhiều" thì case đó không phải smoke. Smoke chỉ gồm case mà đỏ một cái là mọi kết quả sau đó mất nghĩa. Đây là tiêu chí bắt buộc; năm tiêu chí còn lại là bộ lọc thêm.

2.Đi qua, không đi sâu

Một tới ba assertion mỗi case, chỉ ở mức sống hay chết. Không assert business rule, không assert chữ trên nút, không assert định dạng số.

3.Chạm vào hạ tầng dùng chung

Khởi động, đăng nhập, lớp mạng, database và migration, khung điều hướng, push, tải tệp. Hạ tầng chết thì cả ba module chết theo.

4.Phủ bề rộng trước độ sâu

Mỗi module tối thiểu một case. Mười lăm case dồn vào một module là bộ smoke sai hình, dù từng case đều tốt.

5.Ổn định tuyệt đối

Case chập chờn bị gỡ khỏi smoke ngay hôm phát hiện, không chờ sửa xong. "Chạy lại lần nữa xem sao" là câu làm cổng mất hết giá trị.

6.Rẻ và nhanh

Case cần dựng dữ liệu mười phút, hoặc cần hai thiết bị phối hợp, thì hỏi lại: giá trị nó mang có xứng phần ngân sách nó ăn không.

Công thức liệt kê, năm bước

  1. Vẽ trục sống của app

    Cài, mở, đăng nhập, khung điều hướng, một vòng ra server, một hành động sinh dữ liệu ở mỗi module, đăng xuất. Mỗi mắt trên trục là một ứng viên, chưa phải một case chắc chắn.

  2. Chấm điểm từng thành phần nền chung

    Với mỗi thứ trong phần nền chung — tài khoản, phân quyền, push, tải tệp, đồng bộ ngoại tuyến — hỏi "nó chết thì bao nhiêu module chết theo". Từ hai module trở lên thì vào smoke.

  3. Mỗi module lấy đúng một happy path

    Chọn hành động tạo ra giá trị chính của module, đi đường thuận, không nhánh lỗi. Một, không phải ba.

  4. Thêm case chứng minh chính bản build

    Cài đè bản đang phát hành chứ không chỉ cài mới, số phiên bản đúng, mở lên không dừng ở splash, không màn trắng.

  5. Sắp xếp rồi cắt từ dưới

    Sắp theo "gãy thì bao nhiêu user gãy theo", cắt từ dưới lên cho vừa ngân sách. Cắt case, đừng nới ngân sách — nới một lần là nới mãi.

Trục sống của Alliance App

Ba module Chat, Task, Bán hàng cộng phần nền chung — xem phạm vi sản phẩm. Trục sống vẽ ra như sau, mỗi mắt là chỗ đặt câu hỏi của tiêu chí 1:

  1. Cài đặt

    cài mới và cài đè bản trước

  2. Mở app

    qua splash, tới màn đầu tiên

  3. Đăng nhập

    token về, lưu được, đọc lại được

  4. Khung điều hướng

    ba tab vẽ xong nội dung thật

  5. Một vòng ra server và về

    đúng một request đủ chứng minh lớp mạng còn thông

  6. Mỗi module một hành động

    sinh dữ liệu, đọc lại thấy

  7. Đăng xuất

    token xoá, về màn đăng nhập

Đề xuất cho phần nền chung

Vì sao nó ở trong smoke
Đỏ nghĩa là
Cài bản build lên máy sạch, mở tới màn đầu tiên
Không cài được thì không có gì để test
Artifact hỏng, hoặc chữ ký và cấu hình build sai
Cài đè bản đang phát hành, mở lại thấy dữ liệu cũ
Đây là đường 100% user đi, không phải đường dev hay đi
Migration gãy, lỗi đắt nhất vì nó chỉ lộ ra ở user đã có dữ liệu
Đăng nhập bằng tài khoản test, tới màn hình chính
Sau nó là toàn bộ app
Hạ tầng tài khoản gãy, hoặc backend không nhận build này
Mở lại app khi session còn hạn, không bị hỏi đăng nhập lại
Lưu rồi đọc lại token là chỗ gãy lặng lẽ
Token không lưu được, mọi user bị đăng xuất sau mỗi lần mở
Mở lần lượt ba tab, mỗi tab vẽ xong nội dung thật
Một tab treo ở skeleton là một module chết
Khung điều hướng gãy, hoặc một API danh sách gãy
Một request tới backend trả về đúng
Bắt lệch phiên bản giữa app và backend
Giao kèo app và backend đã vỡ, xem backward compatibility
Nhận một push test, bấm vào mở đúng chỗ
Push là nền chung của cả ba module
Đăng ký thiết bị gãy, hoặc deep link gãy
Bật chế độ máy bay rồi mở app, không crash
Case mạng rẻ nhất, bắt được lỗi đắt
App giả định lúc nào cũng có mạng
Đăng xuất, về màn đăng nhập, token bị xoá
Vòng đời phiên phải kín cả hai đầu
Dữ liệu người dùng trước còn lại trên máy

Đề xuất cho ba module

Hành động
Assert ở mức sống hay chết
Chat
Gửi một tin nhắn vào cuộc trò chuyện có sẵn
Tin lên server rồi quay về với trạng thái đã gửi. Không cần máy thứ hai, phối hợp hai máy là việc của critical path
Task
Tạo một công việc, gán cho một người
Công việc hiện trong danh sách sau khi tải lại, đúng người nhận
Bán hàng
Tạo một đơn tới bước xác nhận, dừng trước thanh toán
Đơn hiện trong danh sách với trạng thái đúng. Thanh toán chỉ chạy trên sandbox, smoke không bao giờ chạm tiền thật

Năm cách smoke suite chết

Phình ra thành regression

Mỗi bug lọt ra production lại thêm một case vào smoke. Sáu tháng sau: 120 case, 50 phút, không ai chạy trước khi bàn giao. Luật đổi một đổi một — thêm case mới thì bỏ một case cũ, hoặc để case mới vào regression suite.

Chứa case chập chờn

Đội học được rằng "chạy lại là xanh". Từ lúc đó cổng không chặn gì nữa, chỉ còn tốn mười phút mỗi build.

Assert quá sâu

Đỏ vì đổi chữ trên nút, không vì app hỏng. Smoke đỏ phải luôn nghĩa là "build hỏng", nếu không nó thành tiếng ồn.

Chỉ chạy trên máy mạnh

Xanh trên emulator và máy dev, hỏng trên máy user. Chạy smoke trên máy cấu hình thấp nhất của Tier 1, xem device matrix.

Chạy khi có người nhớ

Smoke thủ công là smoke không chạy. Phần tự động hoá được phải nằm trong CI mỗi build, xem quality gate tự động.

Khi nào chạy, ai chạy

Ai hoặc cái gì chạy
Phạm vi
Mỗi build trên CI
Máy
Phần đã tự động hoá, trên emulator và một máy cloud
Trước khi bàn giao build cho đội test
Người bàn giao
Cả suite, trên một máy thật cấu hình thấp
Sau mỗi lần deploy backend
Máy
Smoke phía API, trên staging rồi trên production
Trước khi mở regression suite
Đội test
Cả suite, đây là entry criteria chứ không phải thủ tục
Ngay sau khi rollout ra nhóm user đầu tiên
Người trực release
Cả suite trên bản tải từ store, xem release từng phần

Smoke ở phía backend

Ở quy mô 500.000 user, một lần deploy backend sai làm cả ba module chết cùng lúc trong khi app không đổi một dòng code. Nên phía server có smoke suite riêng, ngân sách 60 giây, chạy tự động ngay sau mỗi lần deploy:

Health endpoint trả 200

tiến trình sống và nhận được request

Một lượt ghi rồi đọc lại

database còn thông, không chỉ còn kết nối

Một lần phát token rồi dùng token đó

lớp xác thực còn hoạt động

Một job nền được nhận và xử lý

queue không đứng

Đỏ ở đây nghĩa là rollback bản deploy, không phải mở phiếu rồi chờ — xem quy trình release và rollback.

Giới hạn

Smoke không tìm bug mới

Nó phát hiện build chết. Tìm bug là việc của functional, exploratory và regression.

Smoke xanh không phải chỉ số chất lượng

Đừng đưa "tỷ lệ smoke pass" vào báo cáo như một thành tích, xem quality metrics.

Suite này cố tình thiếu

Mỗi lần có người muốn "thêm cho đủ", thứ họ đang muốn viết là regression suite. Cảm giác thiếu là dấu hiệu smoke suite còn đúng hình, không phải dấu hiệu phải bổ sung.