Product Management
Đăng nhập
ESC

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

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

Bài 41 — Test Design Techniques — Black Box

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

Hãy tưởng tượng bạn phải kiểm thử một ô nhập tuổi trên form đăng ký. Ô đó chấp nhận số từ 0 đến 120. Nếu bạn thử nhập 1, 2, 3, 4... cho đến 120, rồi thử thêm vài số âm và vài số lớn, bạn sẽ mất cả buổi sáng mà vẫn không chắc mình đã "phủ" hết các trường hợp quan trọng. Đây chính là bài toán muôn thuở của người làm QA: không bao giờ có đủ thời gian để test tất cả, nhưng vẫn phải tự tin rằng những case quan trọng nhất đã được kiểm tra.

Test Design Techniques — Black Box (kỹ thuật thiết kế test hộp đen) chính là bộ công cụ giúp bạn giải bài toán đó một cách khoa học. "Hộp đen" nghĩa là bạn kiểm thử phần mềm chỉ dựa trên đầu vào (input) và đầu ra (output) kỳ vọng, không cần biết bên trong code viết như thế nào. Bạn nhìn hệ thống như một chiếc hộp kín: đưa dữ liệu vào, quan sát kết quả ra, và so với đặc tả (specification).

Với vai trò QA Leader, đây không chỉ là kỹ năng cá nhân. Khi bạn xây dựng test strategy hay review test case của cả team, chính những kỹ thuật này quyết định chất lượng và độ phủ của bộ test. Một junior không biết Equivalence Partitioning sẽ viết 200 test case dư thừa mà vẫn bỏ sót lỗi; một người thành thạo sẽ viết 15 test case sắc bén, phủ đúng những vùng rủi ro. Trong bài này chúng ta đi sâu vào bốn kỹ thuật hộp đen kinh điển và được dùng nhiều nhất trong thực tế: Equivalence Partitioning, Boundary Value Analysis, Decision Table Testing, và State Transition Testing.

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

Equivalence Partitioning (EP) — Phân vùng tương đương

Ý tưởng nền tảng: chia không gian đầu vào thành các nhóm (partition) mà mọi giá trị trong cùng một nhóm được kỳ vọng xử lý giống hệt nhau. Nếu hệ thống xử lý đúng một giá trị đại diện trong nhóm, thì (theo giả định) nó cũng xử lý đúng mọi giá trị khác trong nhóm đó. Nhờ vậy bạn chỉ cần test một đại diện cho mỗi nhóm thay vì test tất cả.

Quay lại ô nhập tuổi [0–120]:

  • Nhóm hợp lệ (valid): mọi số từ 0 đến 120. Đại diện: chọn 45.
  • Nhóm không hợp lệ — quá nhỏ: số âm như -5, -200. Đại diện: -5.
  • Nhóm không hợp lệ — quá lớn: 121, 500, 9999. Đại diện: 200.
  • Nhóm không hợp lệ — sai kiểu dữ liệu: chữ cái "abc", ký tự đặc biệt "@#", để trống. Mỗi loại là một partition riêng.
Thay vì test 121 giá trị hợp lệ, bạn test 1 giá trị đại diện. Thay vì test vô số số âm, bạn test 1. Từ hàng trăm case rút xuống còn khoảng 5–6 case mà độ phủ logic vẫn tương đương. Đó là sức mạnh của EP.

Nguyên tắc vàng: luôn phân vùng cả valid lẫn invalid. Người mới thường chỉ nghĩ đến dữ liệu đúng mà quên rằng phần lớn lỗi nghiêm trọng nằm ở cách hệ thống xử lý dữ liệu sai.

Boundary Value Analysis (BVA) — Phân tích giá trị biên

EP có một điểm yếu: lỗi thường "ẩn nấp ở biên". Lập trình viên hay viết nhầm < thành <=, hay quên xử lý giá trị đúng ở mép. Vì vậy BVA bổ sung cho EP bằng cách test các giá trị nằm ngay tại ranh giới giữa các partition.

Với ô tuổi [0–120], các giá trị biên cần test là:

  • Ngay dưới biên dưới: -1
  • Đúng biên dưới: 0
  • Ngay trên biên dưới: 1
  • Ngay dưới biên trên: 119
  • Đúng biên trên: 120
  • Ngay trên biên trên: 121
Đây là cách tiếp cận "3 giá trị mỗi biên" (mỗi biên test giá trị trước, tại, và sau). Một biến thể gọn hơn là "2 giá trị mỗi biên" chỉ test giá trị hợp lệ mép và giá trị không hợp lệ liền kề (0, -1, 120, 121). Trong thực tế, tỷ lệ lỗi phát hiện ở biên cực kỳ cao — nhiều nghiên cứu cho thấy phần lớn defect về logic điều kiện nằm ngay tại boundary.

EP và BVA gần như luôn đi cặp: EP giúp bạn giảm số lượng case, BVA giúp bạn không bỏ sót lỗi ở mép của mỗi vùng.

Decision Table Testing — Bảng quyết định

Khi output phụ thuộc vào nhiều điều kiện kết hợp, EP và BVA không đủ. Lúc này ta dùng Decision Table: một bảng liệt kê tất cả tổ hợp điều kiện (conditions) và hành động (actions) tương ứng.

Ví dụ chính sách giảm giá của một sàn thương mại điện tử: khách hàng VIP được giảm 10%, đơn trên 500.000đ được miễn phí ship. Hai điều kiện, mỗi điều kiện có 2 trạng thái (đúng/sai), tạo ra 4 tổ hợp — mỗi tổ hợp là một test case với hành động kỳ vọng rõ ràng. Decision Table buộc bạn suy nghĩ có hệ thống về mọi tổ hợp, tránh bỏ sót những trường hợp "vừa VIP vừa đơn nhỏ" hay "không VIP nhưng đơn lớn".

State Transition Testing — Chuyển trạng thái

Nhiều hệ thống có "trạng thái" (state) và hành vi thay đổi tùy trạng thái hiện tại. Ví dụ: máy ATM, đơn hàng (chờ thanh toán → đã thanh toán → đang giao → hoàn tất → hủy), hoặc tài khoản người dùng (active → locked sau 3 lần sai mật khẩu). State Transition Testing kiểm tra: từ mỗi trạng thái, khi có một sự kiện (event) xảy ra, hệ thống có chuyển sang đúng trạng thái kế tiếp không, và những chuyển đổi không được phép có bị chặn không.

Tình huống thực tế

Ví dụ 1 — Momo và ô nhập số tiền chuyển khoản

Một team QA tại một ví điện tử lớn ở Việt Nam (tạm gọi theo mô hình Momo) kiểm thử tính năng chuyển tiền. Đặc tả: số tiền chuyển tối thiểu 10.000đ, tối đa 20.000.000đ mỗi giao dịch.

Ban đầu, một bạn tester mới viết tới 40 test case: 10.000, 50.000, 100.000, 200.000... nhập gần như mọi mốc tròn. Chị QA Lead review và chỉ ra vấn đề: 40 case này thực chất chỉ phủ một partition hợp lệ duy nhất, dư thừa khủng khiếp, trong khi bỏ sót hoàn toàn vùng biên và vùng invalid.

Áp dụng EP + BVA, cả team rút gọn lại thành bộ 9 case tinh gọn: một giá trị đại diện hợp lệ (5.000.000đ); các biên 9.999đ / 10.000đ / 10.001đ / 19.999.999đ / 20.000.000đ / 20.000.001đ; cộng thêm invalid: nhập số âm và nhập số 0.

Kết quả: chính case biên 20.000.001đ phát hiện một lỗi nghiêm trọng — hệ thống dùng điều kiện <= sai chỗ nên vẫn cho phép chuyển 20.000.001đ, vượt hạn mức. Bài học: bộ test ít hơn 4 lần nhưng lại tìm ra lỗi mà bộ 40 case "chăm chỉ" kia bỏ lọt. Số lượng test case không phản ánh chất lượng test.

Ví dụ 2 — Shopee và chính sách miễn phí vận chuyển

Một team kiểm thử tính năng khuyến mãi trên một sàn TMĐT (mô hình Shopee) với logic: khách được miễn phí ship nếu thỏa mãn — là thành viên Shopee (Yes/No), đơn hàng ≥ 300.000đ (Yes/No), và dùng mã freeship (Yes/No). Ba điều kiện, tạo ra 8 tổ hợp.

Ban đầu team chỉ test "happy path": thành viên + đơn lớn + có mã → miễn phí ship. Đúng như kỳ vọng. Nhưng khi lập Decision Table đầy đủ 8 dòng, họ phát hiện một tổ hợp bị bỏ sót: không phải thành viên + đơn 350.000đ + có mã freeship. Theo đặc tả, mã freeship phải áp dụng cho cả khách vãng lai, nhưng code lại yêu cầu bắt buộc là thành viên. Lỗi này khiến một chiến dịch marketing thu hút khách mới bị vô hiệu — người mới bấm mã mà không được miễn ship, tỷ lệ bỏ giỏ hàng tăng vọt.

Bài học: khi output phụ thuộc nhiều điều kiện, "happy path" là cái bẫy. Decision Table buộc bạn nhìn thấy toàn bộ ma trận tổ hợp, và chính những dòng ít ai nghĩ tới lại là nơi ẩn lỗi kinh doanh nghiêm trọng.

Ví dụ 3 — Ngân hàng số và trạng thái đăng nhập

Một ngân hàng số ở Đông Nam Á (mô hình như TNEX hay Cake) có quy tắc bảo mật: tài khoản bị khóa sau 5 lần nhập sai mật khẩu liên tiếp; nhập đúng ở lần thứ 4 sẽ reset bộ đếm về 0.

Team QA vẽ sơ đồ chuyển trạng thái với các state: Active (0–4 lần sai) và Locked. Sự kiện gồm "nhập đúng" và "nhập sai". Họ test từng chuyển đổi: sai lần 1→2→3→4, rồi ở lần 4 nhập đúng (kỳ vọng: về Active, đếm = 0), rồi lại sai 5 lần liên tiếp (kỳ vọng: Locked).

Kết quả phát hiện lỗi ở đúng cơ chế reset: khi nhập đúng ở lần thứ 4, hệ thống đăng nhập được nhưng không reset bộ đếm sai. Người dùng lần sau chỉ cần sai thêm 1 lần là bị khóa oan. Nếu chỉ test tuyến tính "sai 5 lần thì khóa" thì không bao giờ lộ ra bug này — phải test chuyển trạng thái reset mới thấy.

Bài học: với hệ thống có bộ đếm, trạng thái và luồng nghiệp vụ, State Transition Testing giúp bạn phát hiện những lỗi ở các đường chuyển đổi "ít đi qua" mà test tuần tự bỏ sót.

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

Đây là quy trình bạn có thể áp dụng để thiết kế test case hộp đen cho bất kỳ tính năng nào:

Bước 1 — Đọc và làm rõ đặc tả. Xác định rõ mỗi trường input có kiểu dữ liệu gì, giới hạn nào, các điều kiện nghiệp vụ ra sao. Nếu đặc tả mập mờ ("số tiền hợp lý"), hỏi lại BA/PO ngay — không tự đoán.

Bước 2 — Liệt kê partition cho từng input (EP). Với mỗi trường, chia thành các nhóm valid và invalid. Đừng quên các invalid phi số như để trống, sai định dạng, ký tự đặc biệt.

Bước 3 — Xác định giá trị biên (BVA). Với mỗi partition có ranh giới số hoặc độ dài chuỗi, ghi ra giá trị ngay dưới biên, tại biên, và ngay trên biên.

Bước 4 — Lập Decision Table nếu output phụ thuộc nhiều điều kiện. Liệt kê tất cả điều kiện, tính số tổ hợp (2^n với n điều kiện nhị phân), điền hành động kỳ vọng cho từng dòng. Có thể gộp/lược các dòng tương đương để giảm số case.

Bước 5 — Vẽ sơ đồ trạng thái nếu tính năng có state. Xác định các state, event, chuyển đổi hợp lệ và không hợp lệ. Thiết kế case đi qua từng chuyển đổi, đặc biệt các chuyển đổi hiếm và các đường bị cấm.

Bước 6 — Tổng hợp thành test case và loại trùng. Một case tốt thường phủ được nhiều mục tiêu (một input đại diện có thể kết hợp với một biên của input khác). Gộp lại để bộ test gọn nhất mà vẫn đủ phủ.

Bước 7 — Gắn mức ưu tiên. Đánh dấu case nào là critical (liên quan tiền, bảo mật, biên) để chạy trước khi thời gian eo hẹp.

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

Lỗi 1 — Chỉ test dữ liệu hợp lệ. Đây là lỗi phổ biến nhất của người mới. Phần lớn defect nghiêm trọng lại nằm ở cách hệ thống xử lý input sai. Luôn dành ít nhất một nửa số case cho các partition invalid.

Lỗi 2 — Quên biên. Test 5 và 500 cho khoảng [0–120] mà không test 0, 120, -1, 121. Nhớ: lỗi thích trốn ở mép. Nếu chỉ có thời gian test một thứ, hãy test biên.

Lỗi 3 — Nhầm số lượng với chất lượng. Viết 100 case cùng một partition không tốt hơn 5 case phủ 5 partition khác nhau. Reviewer nên nhìn vào độ phủ partition, không phải con số tổng.

Lỗi 4 — Bỏ qua tổ hợp trong logic đa điều kiện. Chỉ test happy path khi có nhiều điều kiện là công thức để lọt bug. Dùng Decision Table.

Lỗi 5 — Bỏ qua các chuyển trạng thái "không được phép". Ví dụ: có thể hủy một đơn đã giao xong không? Test cả những đường chuyển đổi mà hệ thống phải chặn.

Mẹo: Kết hợp các kỹ thuật, đừng dùng đơn lẻ. Một tính năng thực tế thường cần EP + BVA cho từng trường, cộng Decision Table cho logic nghiệp vụ, cộng State Transition nếu có trạng thái. Mẹo: Dùng bảng để trình bày test design — reviewer dễ soi lỗ hổng hơn nhiều so với danh sách dài. Mẹo: Khi hạn mức thời gian, ưu tiên biên và invalid trước, vì đó là nơi tỷ lệ bắt lỗi cao nhất.

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

Bài 1 — EP + BVA. Một form đăng ký yêu cầu mật khẩu dài 8–16 ký tự. Hãy liệt kê các partition (valid/invalid) và tất cả giá trị biên cần test về độ dài. Gợi ý: chú ý các giá trị 7, 8, 9, 15, 16, 17 và trường hợp để trống.

Bài 2 — Decision Table. Một ứng dụng gọi xe tính giá: giờ cao điểm (Yes/No), trời mưa (Yes/No), khách hàng có gói hội viên (Yes/No). Hãy lập bảng quyết định đầy đủ các tổ hợp và tự đặt ra hành động (mức phụ phí/giảm giá) hợp lý cho từng dòng. Đếm xem có bao nhiêu test case.

Bài 3 — State Transition. Một đơn hàng có các trạng thái: Chờ xác nhận → Đã xác nhận → Đang giao → Hoàn tất, và có thể Hủy (chỉ khi chưa Đang giao). Hãy vẽ sơ đồ trạng thái, liệt kê các chuyển đổi hợp lệ và ít nhất 3 chuyển đổi phải bị chặn.

Bài 4 — Tổng hợp. Chọn một tính năng bạn đang làm việc thực tế và áp dụng đủ 7 bước trong phần Hướng dẫn từng bước. So sánh số test case bạn viết trước và sau khi áp dụng kỹ thuật.

Tóm tắt

Kỹ thuật thiết kế test hộp đen là bộ công cụ nền tảng giúp bạn thiết kế test case có hệ thống, độ phủ cao và số lượng tối ưu, chỉ dựa trên input/output và đặc tả mà không cần đọc code.

  • Equivalence Partitioning (EP): chia input thành nhóm tương đương, test một đại diện mỗi nhóm — giảm mạnh số case. Luôn phân cả valid lẫn invalid.
  • Boundary Value Analysis (BVA): test giá trị ngay tại và liền kề ranh giới — nơi lỗi hay ẩn nấp. Luôn đi cặp với EP.
  • Decision Table: liệt kê mọi tổ hợp điều kiện khi output phụ thuộc nhiều điều kiện — chống bỏ sót tổ hợp nghiệp vụ.
  • State Transition: kiểm tra các chuyển trạng thái hợp lệ và không hợp lệ — bắt lỗi ở luồng nghiệp vụ có trạng thái.
Ba tình huống Momo, Shopee và ngân hàng số cho thấy một chân lý: chất lượng test không nằm ở số lượng case, mà ở việc phủ đúng các vùng rủi ro. Là QA Leader, khi bạn review test design của team, hãy hỏi: "Đã phủ hết partition chưa? Đã test biên chưa? Đã xét đủ tổ hợp chưa? Đã kiểm tra các chuyển trạng thái bị cấm chưa?" — bốn câu hỏi đó chính là bốn kỹ thuật của bài học này.

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