Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn đang test tính năng đăng nhập của một app ngân hàng. Người dùng nhập đúng mật khẩu, nhưng tài khoản đang bị khóa, đồng thời thiết bị lại chưa được đăng ký. Vậy hệ thống phải hiện thông báo gì? Cho vào hay chặn lại? Còn nếu mật khẩu sai nhưng tài khoản chưa khóa thì sao? Chỉ với ba yếu tố đơn giản — mật khẩu, trạng thái khóa, thiết bị — bạn đã có tới tám tổ hợp cần kiểm tra. Và mỗi tổ hợp lại có thể dẫn tới một hành vi khác nhau.
Đây chính là loại bài toán mà nhiều tester non tay hay bỏ sót. Họ test được vài trường hợp "hiển nhiên", rồi bug lọt lưới ở đúng cái tổ hợp mà không ai nghĩ tới. Khách hàng nhập đúng mật khẩu mà vẫn bị chặn, hoặc tệ hơn — tài khoản đã khóa mà vẫn đăng nhập được. Những lỗi kiểu này không phải do code khó, mà do không ai liệt kê đủ các trường hợp trước khi viết test.
Decision Table Testing (kiểm thử bằng bảng quyết định) ra đời để giải quyết chính xác vấn đề đó. Nó là một kỹ thuật thiết kế test case có cấu trúc, giúp bạn liệt kê toàn bộ tổ hợp giữa các điều kiện đầu vào và hành động đầu ra tương ứng, một cách hệ thống, không bỏ sót. Trong bài trước bạn đã học Equivalence Partitioning và Boundary Value Analysis — những kỹ thuật tập trung vào từng biến đầu vào riêng lẻ. Decision Table đi xa hơn: nó xử lý bài toán khi output phụ thuộc vào sự kết hợp của nhiều input cùng lúc. Đây là kỹ thuật bạn sẽ dùng gần như mỗi ngày khi test các nghiệp vụ có logic điều kiện phức tạp.
Khái niệm cốt lõi
Decision Table là gì?
Decision Table là một bảng gồm hai phần chính: các điều kiện (conditions) ở phía trên và các hành động (actions) ở phía dưới. Mỗi cột của bảng là một rule (quy tắc) — tức là một kịch bản cụ thể, thể hiện một tổ hợp giá trị của các điều kiện, dẫn tới một hoặc nhiều hành động.
Cấu trúc kinh điển của một bảng quyết định như sau:
| Phần | Ý nghĩa |
|---|---|
| Conditions (điều kiện) | Các đầu vào ảnh hưởng đến kết quả, thường ở dạng đúng/sai (T/F) |
| Actions (hành động) | Kết quả hệ thống thực hiện với mỗi tổ hợp điều kiện |
| Rules (cột) | Mỗi cột = một tổ hợp điều kiện + hành động tương ứng |
Vì sao phải tính đủ tổ hợp?
Nếu bạn có n điều kiện, mỗi điều kiện chỉ có hai giá trị (đúng/sai), thì tổng số tổ hợp lý thuyết là 2 mũ n. Với 2 điều kiện là 4 cột, 3 điều kiện là 8 cột, 4 điều kiện là 16 cột. Con số này tăng rất nhanh, nên Decision Table vừa là công cụ liệt kê, vừa là lời cảnh báo: khi số điều kiện quá nhiều, bạn cần kỹ thuật rút gọn (sẽ nói ở phần sau).
Limited-entry vs Extended-entry
Có hai kiểu bảng bạn nên phân biệt:
- Limited-entry table: mỗi điều kiện chỉ nhận giá trị nhị phân — True (T) hoặc False (F). Đây là dạng phổ biến và dễ đọc nhất.
- Extended-entry table: điều kiện có thể nhận nhiều giá trị hơn hai, ví dụ "Hạng thành viên" có thể là Silver / Gold / Platinum. Dạng này gọn hơn khi biến có nhiều mức, nhưng cần đọc kỹ hơn.
Quan hệ với các kỹ thuật khác
Decision Table không thay thế Equivalence Partitioning hay Boundary Value Analysis, mà bổ sung cho chúng. Trong thực tế, bạn thường dùng EP để xác định các giá trị đại diện cho mỗi điều kiện, rồi dùng Decision Table để tổ hợp chúng lại. Điểm mạnh riêng của Decision Table là nó buộc bạn phải suy nghĩ về sự tương tác giữa các điều kiện — điều mà các kỹ thuật kia không làm được.
Tình huống thực tế
Ví dụ 1: Chính sách giảm giá của ShopeeFood
Giả sử ShopeeFood áp dụng chính sách khuyến mãi: đơn hàng được freeship khi thỏa mãn điều kiện. Sau khi đọc tài liệu nghiệp vụ, bạn xác định có ba điều kiện:
- C1: Đơn hàng có giá trị từ 50.000đ trở lên
- C2: Người dùng là thành viên ShopeeFood Extra (gói trả phí)
- C3: Quán ăn nằm trong bán kính 3km
- A1: Miễn phí giao hàng (freeship)
- A2: Hiển thị nhãn "Giao nhanh"
| Điều kiện | R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 |
|---|---|---|---|---|---|---|---|---|
| C1: Đơn ≥ 50k | T | T | T | T | F | F | F | F |
| C2: Thành viên Extra | T | T | F | F | T | T | F | F |
| C3: Trong 3km | T | F | T | F | T | F | T | F |
| A1: Freeship | Có | Có | Có | Không | Có | Có | Không | Không |
| A2: Nhãn Giao nhanh | Có | Không | Có | Không | Có | Không | Có | Không |
Bài học rút ra: chỉ khi trải toàn bộ 8 cột ra, bạn mới phát hiện những case dễ bị bỏ sót — ví dụ R6 (đơn nhỏ, là thành viên Extra, nhưng ngoài 3km): người này vẫn được freeship vì là Extra, nhưng KHÔNG có nhãn Giao nhanh. Nếu chỉ test "bằng tay theo cảm giác", rất dễ bỏ qua case tréo ngoe này, và đó thường chính là chỗ lập trình viên code sai.
Ví dụ 2: Xét duyệt khoản vay tại một fintech Việt Nam
Một công ty fintech cho vay tiêu dùng (kiểu như một sản phẩm vay nhanh trên app) có quy tắc duyệt hồ sơ dựa trên ba điều kiện:
- C1: Điểm tín dụng ≥ 600
- C2: Thu nhập hàng tháng ≥ 8 triệu đồng
- C3: Có lịch sử nợ xấu trong 12 tháng qua
- A1: Duyệt tự động
- A2: Chuyển thẩm định thủ công
- A3: Từ chối
| Điều kiện | R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 |
|---|---|---|---|---|---|---|---|---|
| C1: Điểm ≥ 600 | T | T | T | T | F | F | F | F |
| C2: Thu nhập ≥ 8tr | T | T | F | F | T | T | F | F |
| C3: Có nợ xấu | T | F | T | F | T | F | T | F |
| A1: Duyệt tự động | X | |||||||
| A2: Thẩm định thủ công | X | X | X | |||||
| A3: Từ chối | X | X | X | X |
Bài học rút ra: Decision Table giúp bạn — và cả team — nhìn ra quy tắc ẩn mà tài liệu nghiệp vụ có khi viết mập mờ. Khi bạn đưa bảng này cho Business Analyst xem, họ có thể phát hiện "à, R5 lẽ ra phải là từ chối chứ không phải thẩm định thủ công". Nghĩa là Decision Table không chỉ để test, nó còn là công cụ làm rõ yêu cầu trước khi lập trình viên viết code. Rất nhiều bug được ngăn chặn ngay từ khâu này.
Ví dụ 3: Cổng thanh toán VNPay và trạng thái giao dịch
Một sàn thương mại điện tử tích hợp VNPay. Khi khách thanh toán xong, hệ thống nhận callback và phải quyết định trạng thái đơn hàng dựa trên:
- C1: Chữ ký (secure hash) hợp lệ
- C2: Mã phản hồi từ VNPay là "00" (thành công)
- C3: Số tiền callback khớp với số tiền đơn hàng
- A1: Cập nhật đơn "Đã thanh toán"
- A2: Giữ đơn "Chờ xử lý" và ghi log cảnh báo
- A3: Từ chối, ghi nhận nghi ngờ gian lận
Bài học rút ra: không phải lúc nào cũng cần trải đủ 8 cột. Khi một điều kiện quyết định kết quả bất kể các điều kiện khác, ta dùng ký hiệu "—" (don't care) để gộp nhiều cột lại. Điều này dẫn ta tới kỹ thuật rút gọn bảng.
Hướng dẫn từng bước
Dưới đây là quy trình 6 bước để xây dựng và dùng một Decision Table trong công việc thực tế:
Bước 1 — Xác định các điều kiện. Đọc kỹ yêu cầu nghiệp vụ (requirement/user story) và gạch chân mọi yếu tố đầu vào ảnh hưởng đến kết quả. Trong ví dụ ShopeeFood đó là giá trị đơn, gói thành viên, khoảng cách. Cố gắng diễn đạt mỗi điều kiện thành một câu có thể trả lời Đúng/Sai.
Bước 2 — Xác định các hành động. Liệt kê tất cả kết quả/hành động mà hệ thống có thể thực hiện: hiển thị thông báo gì, cho phép hay chặn, tính phí bao nhiêu, chuyển sang màn hình nào.
Bước 3 — Tính số cột và vẽ khung bảng. Với n điều kiện nhị phân, bạn có 2 mũ n cột. Điền giá trị T/F theo quy tắc "chia đôi": điều kiện đầu tiên nửa đầu T nửa sau F, điều kiện thứ hai đan xen theo cụm nhỏ hơn, cứ thế. Cách điền máy móc này đảm bảo bạn không bỏ sót tổ hợp nào.
Bước 4 — Điền hành động cho từng cột. Với mỗi cột, đọc tổ hợp điều kiện rồi đối chiếu quy tắc nghiệp vụ để đánh dấu hành động tương ứng. Đây là bước dễ lộ ra mâu thuẫn hoặc lỗ hổng trong yêu cầu — hãy hỏi lại BA ngay khi thấy cột nào không rõ.
Bước 5 — Rút gọn bảng (nếu cần). Nếu hai cột có hành động giống nhau và chỉ khác nhau ở một điều kiện, bạn có thể gộp lại và đánh dấu điều kiện đó là "—" (don't care). Ở ví dụ VNPay, cả bốn cột có C1 = F đều dẫn tới "nghi ngờ gian lận", nên gộp thành một rule duy nhất với C2, C3 là "—".
Bước 6 — Chuyển mỗi cột thành một test case. Mỗi rule (cột) trở thành ít nhất một test case: dữ liệu đầu vào lấy từ giá trị điều kiện, kết quả mong đợi lấy từ hành động. Đặt tên test case rõ ràng, ví dụ "TC_ShopeeFood_R6: Đơn nhỏ + Extra + ngoài 3km → Freeship, không có nhãn Giao nhanh".
Lỗi thường gặp & mẹo
Lỗi 1 — Bỏ sót điều kiện. Nhiều tester chỉ đưa vào bảng những điều kiện "thấy rõ" mà quên các yếu tố ngầm, ví dụ trạng thái tài khoản, múi giờ, hay flag cấu hình. Mẹo: rà lại requirement và hỏi "còn yếu tố nào có thể làm kết quả thay đổi không?".
Lỗi 2 — Nhầm số tổ hợp. Điền thiếu cột là lỗi rất phổ biến khi vẽ tay. Luôn kiểm tra lại: số cột phải đúng bằng 2 mũ (số điều kiện) trước khi rút gọn.
Lỗi 3 — Bùng nổ tổ hợp (combinatorial explosion). Với 6 điều kiện bạn đã có 64 cột, không ai test nổi thủ công. Khi gặp trường hợp này, đừng cố trải hết — hãy tách bài toán thành các bảng nhỏ độc lập, hoặc chuyển sang kỹ thuật Pairwise Testing (sẽ học ở bài 12) để giảm số case mà vẫn phủ được các cặp tương tác quan trọng.
Lỗi 4 — Quên các cột "impossible". Đôi khi một tổ hợp là bất khả thi về mặt logic (ví dụ "chưa đăng nhập" nhưng "là thành viên VIP"). Đừng xóa lặng lẽ — hãy đánh dấu và ghi chú lý do, vì đôi khi cái bạn tưởng bất khả thi lại xảy ra do bug.
Mẹo vàng: Decision Table đẹp nhất khi bạn dùng nó trước khi code được viết, đưa cho BA và Dev cùng review. Lúc đó nó không chỉ là công cụ test mà là công cụ thống nhất hiểu biết. Rất nhiều "bug" thực chất là hiểu sai yêu cầu, và bảng này phơi bày điều đó ngay từ đầu.
Mẹo về công cụ: bạn có thể vẽ bảng bằng Excel/Google Sheets, hoặc dùng các công cụ chuyên biệt. Với bảng nhỏ, Sheets là đủ và tiện chia sẻ với cả team.
Bài tập thực hành
Hãy áp dụng ngay với một tình huống Việt Nam quen thuộc: chính sách tích điểm của một chuỗi cà phê (kiểu The Coffee House). Quy tắc: khách được cộng điểm x2 khi thỏa mãn các điều kiện sau:
- C1: Đơn hàng ≥ 100.000đ
- C2: Đặt qua app (không phải mua tại quầy)
- C3: Trong khung giờ vàng 14h–16h
- Xác định số cột của bảng quyết định (gợi ý: 2 mũ mấy?).
- Vẽ đầy đủ bảng limited-entry với 3 điều kiện trên, giả định quy tắc "x2 điểm nếu (đặt qua app) VÀ (đơn ≥ 100k HOẶC trong giờ vàng)".
- Đánh dấu hành động (x2 điểm: Có/Không) cho từng cột.
- Viết ra tên đầy đủ cho ít nhất 3 test case tương ứng với 3 cột bạn thấy dễ bị bỏ sót nhất.
- Câu hỏi nâng cao: nếu chuỗi cà phê bổ sung thêm điều kiện C4 "là thành viên hạng Gold", bảng sẽ có bao nhiêu cột? Bạn sẽ xử lý sự bùng nổ tổ hợp này thế nào?
Tóm tắt
Decision Table Testing là kỹ thuật thiết kế test case dành cho những tình huống mà kết quả phụ thuộc vào tổ hợp của nhiều điều kiện đầu vào. Bằng cách liệt kê có hệ thống mọi tổ hợp giữa các điều kiện (conditions) và hành động (actions), bạn đảm bảo không bỏ sót trường hợp nào — đặc biệt là những case tréo ngoe mà test "theo cảm giác" hay lọt lưới.
Những điểm cần nhớ:
- Với n điều kiện nhị phân, có 2 mũ n tổ hợp; mỗi cột là một rule và trở thành một test case.
- Dùng ký hiệu "—" (don't care) để rút gọn khi một điều kiện quyết định kết quả bất kể các điều kiện còn lại.
- Khi số điều kiện lớn gây bùng nổ tổ hợp, hãy tách bảng hoặc chuyển sang Pairwise Testing.
- Sức mạnh lớn nhất của Decision Table không chỉ ở khâu test, mà ở khâu làm rõ yêu cầu cùng BA và Dev trước khi code được viết.