Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn được thuê để kiểm tra chất lượng một chiếc máy pha cà phê trước khi nó xuất xưởng. Có ba cách để làm việc này. Cách thứ nhất: bạn chỉ cầm máy lên, cắm điện, bấm nút và xem cà phê chảy ra có đúng như quảng cáo không — bạn không cần biết bên trong máy có bao nhiêu con chip, bao nhiêu ống dẫn. Cách thứ hai: bạn tháo tung chiếc máy ra, kiểm tra từng mạch điện, từng đoạn ống, từng van, để chắc chắn không có dây nào chập, không có van nào bị bịt. Cách thứ ba: bạn vừa bấm nút thử như người dùng, vừa liếc bản vẽ kỹ thuật để biết chỗ nào hay hỏng mà tập trung vào.
Ba cách đó chính là Black-box, White-box và Grey-box testing. Đây không phải là ba "loại" kiểm thử tách biệt để bạn chọn một và bỏ hai cái còn lại, mà là ba góc nhìn — ba mức độ hiểu biết về code bên trong hệ thống. Hiểu rõ ba góc nhìn này là nền tảng để bạn đọc được các bài sau về kỹ thuật thiết kế test, về tự động hóa, về vai trò SDET. Nếu một nhà tuyển dụng QA hỏi bạn "Em phân biệt black-box và white-box thế nào?", đây là câu trả lời phải trôi chảy như bảng cửu chương. Trong bài này, tôi sẽ giúp bạn nắm chắc bản chất, biết khi nào dùng góc nhìn nào, và tránh những hiểu lầm phổ biến khiến nhiều bạn junior trả lời phỏng vấn lúng túng.
Khái niệm cốt lõi
Điểm mấu chốt để phân biệt ba góc nhìn nằm ở một câu hỏi duy nhất: Người kiểm thử biết bao nhiêu về cấu trúc code bên trong (internal structure) khi thiết kế test?
Black-box testing — Kiểm thử hộp đen
"Hộp đen" nghĩa là hệ thống với bạn giống như một cái hộp kín màu đen: bạn thấy đầu vào (input) và đầu ra (output), nhưng không nhìn thấy — và không cần quan tâm — chuyện gì diễn ra bên trong.
Với black-box, bạn thiết kế test dựa hoàn toàn trên đặc tả (specification), yêu cầu (requirement), user story và hành vi mong đợi của hệ thống. Bạn đóng vai người dùng cuối. Bạn không đọc source code, không quan tâm hệ thống viết bằng PHP hay Java, dùng vòng lặp for hay while.
Ví dụ đơn giản: một ô nhập số điện thoại Việt Nam yêu cầu "10 chữ số, bắt đầu bằng 0". Là tester black-box, bạn thử nhập 0987654321 (hợp lệ), 098765432 (thiếu số), 1987654321 (không bắt đầu bằng 0), 098765432a (có chữ cái) — mà không cần biết lập trình viên đã viết regex nào để kiểm tra.
Các kỹ thuật black-box kinh điển mà bạn sẽ học sâu ở các bài sau gồm: Equivalence Partitioning (chia lớp tương đương), Boundary Value Analysis (phân tích giá trị biên), Decision Table (bảng quyết định), State Transition (chuyển trạng thái). Điểm chung: tất cả đều xuất phát từ yêu cầu, không từ code.
Ưu điểm: tester không cần biết lập trình, test phản ánh đúng góc nhìn người dùng, không bị thiên kiến theo cách code được viết. Nhược điểm: bạn có thể bỏ sót những nhánh code ẩn (hidden path) mà đặc tả không nhắc tới, và khó biết mình đã test được bao nhiêu phần trăm code (code coverage).
White-box testing — Kiểm thử hộp trắng
"Hộp trắng" (còn gọi là glass-box — hộp thủy tinh, hay structural testing — kiểm thử cấu trúc) là ngược lại hoàn toàn: hộp trong suốt, bạn nhìn thấy toàn bộ code bên trong và thiết kế test dựa trên chính cấu trúc đó.
Người làm white-box phải đọc được và hiểu source code. Mục tiêu là đi qua càng nhiều đường đi trong code càng tốt: mỗi câu lệnh (statement), mỗi nhánh rẽ if/else (branch), mỗi điều kiện logic (condition), mỗi vòng lặp.
Ví dụ: có đoạn code tính phí ship — if (donHang >= 500000) phiShip = 0; else phiShip = 30000;. Tester black-box chỉ biết "đơn từ 500k được free ship". Nhưng tester white-box nhìn thấy có đúng hai nhánh, nên chủ động thiết kế ít nhất một test cho nhánh >= 500000 và một test cho nhánh < 500000 để đảm bảo cả hai nhánh đều được thực thi. Đây là khái niệm branch coverage.
Các độ đo bao phủ (coverage) trong white-box: statement coverage (bao phủ câu lệnh), branch/decision coverage (bao phủ nhánh), path coverage (bao phủ đường đi), condition coverage (bao phủ điều kiện con). White-box thường gắn với unit test và integration test — chủ đề của Bài 6 về Test Pyramid.
Ưu điểm: phát hiện được lỗi logic ẩn sâu, dead code (code không bao giờ chạy), các nhánh bị bỏ quên, và đo được coverage cụ thể. Nhược điểm: đòi hỏi kỹ năng lập trình; tester dễ bị "cận thị" — chỉ thấy code đang có mà quên rằng một tính năng còn thiếu hoàn toàn thì trong code chẳng có gì để test, nên black-box mới bắt được lỗi "thiếu chức năng".
Grey-box testing — Kiểm thử hộp xám
Grey-box là sự pha trộn của hai góc nhìn trên: bạn kiểm thử chủ yếu từ bên ngoài như black-box, nhưng có một phần hiểu biết về nội bộ — kiến trúc hệ thống, cấu trúc database, thiết kế API, thuật toán chính. Không phải đọc từng dòng code, mà là "biết đủ" để thiết kế test thông minh hơn.
Ví dụ điển hình: bạn test chức năng đăng ký tài khoản. Ở góc nhìn black-box, bạn chỉ điền form và bấm "Đăng ký". Nhưng nếu bạn biết rằng hệ thống lưu email vào cột email có ràng buộc UNIQUE trong database, bạn sẽ chủ động thiết kế test "đăng ký hai lần cùng một email" để kiểm tra ràng buộc đó, đồng thời mở database ra kiểm tra xem bản ghi được lưu đúng chưa, mật khẩu đã được hash chưa. Đó chính là grey-box: dùng kiến thức nội bộ để nhắm test có mục tiêu và kiểm chứng ở nhiều lớp.
Grey-box đặc biệt phổ biến trong API testing và database testing (Bài 49, 50), nơi bạn cần hiểu cấu trúc request/response và schema dữ liệu để test hiệu quả. Đây cũng là góc nhìn mà phần lớn tester chuyên nghiệp làm việc hằng ngày — hiếm ai làm thuần black-box 100% hay white-box 100%.
Bảng so sánh nhanh
| Tiêu chí | Black-box | White-box | Grey-box |
|---|---|---|---|
| Biết code bên trong? | Không | Biết toàn bộ | Biết một phần |
| Dựa trên | Yêu cầu, spec | Cấu trúc code | Kiến trúc + spec |
| Cần biết lập trình? | Không bắt buộc | Bắt buộc | Nên có |
| Cấp độ điển hình | System, Acceptance | Unit, Integration | Integration, API |
| Người thực hiện | QA, tester | Developer, SDET | QA có kỹ thuật |
Tình huống thực tế
Tình huống 1 — Sàn TMĐT đặt hàng và lỗi "free ship" ẩn
Một công ty thương mại điện tử tại TP.HCM (giả định tên là ShopViet) tung chương trình "miễn phí vận chuyển cho đơn từ 500.000đ". Đội QA làm black-box: họ thử đơn 400k (tính phí ship), đơn 600k (free ship) — cả hai chạy đúng, họ cho pass.
Ba ngày sau, kế toán phát hiện có hàng loạt đơn đúng bằng 500.000đ vẫn bị tính phí ship 30.000đ, khiến khách khiếu nại. Khi một SDET đọc code (white-box), họ thấy lập trình viên viết nhầm if (donHang > 500000) thay vì >= 500000. Nhánh "bằng đúng 500k" rơi vào else.
Bài học: Tester black-box đã bỏ sót giá trị biên 500k. Nếu áp dụng góc nhìn white-box (nhìn thấy điều kiện > và cố tình test đúng ranh giới), hoặc chí ít là kỹ thuật Boundary Value Analysis từ góc nhìn black-box, lỗi này đã lộ ra ngay. Đây là minh chứng vì sao ba góc nhìn bổ sung cho nhau, không thay thế nhau.
Tình huống 2 — Ví điện tử và ràng buộc số dư âm
Một startup ví điện tử ở Đông Nam Á (giả định PayNow) có tính năng chuyển tiền. Tester grey-box được cấp quyền xem thiết kế database và biết bảng vi có cột so_du kiểu DECIMAL không cho phép âm ở tầng nghiệp vụ, nhưng ở tầng database lại cho phép giá trị âm (không có ràng buộc CHECK so_du >= 0).
Nhờ hiểu biết nội bộ này, tester thiết kế một kịch bản grey-box tinh vi: gửi hai request chuyển tiền đồng thời (race condition) từ một ví có số dư 100.000đ, mỗi lần chuyển 100.000đ. Kết quả: cả hai request cùng đọc số dư 100k, cùng cho phép, và ví bị âm -100.000đ. Sau khi test, họ mở thẳng database kiểm tra so_du = -100000 để xác nhận lỗi.
Bài học: Một tester black-box thuần túy gần như không thể nghĩ ra kịch bản race condition này, vì từ giao diện mọi thứ trông bình thường. Chính hiểu biết về cấu trúc dữ liệu và cơ chế đồng thời (grey-box) đã dẫn đường đến một lỗ hổng nghiêm trọng về tài chính.
Tình huống 3 — Chia đội theo góc nhìn ở một công ty outsourcing
Một công ty outsourcing tại Hà Nội nhận dự án cho khách Nhật. Họ tổ chức đội theo ba lớp: Developer viết unit test white-box cho từng hàm (đạt mục tiêu 80% branch coverage trước khi merge); đội SDET viết integration test grey-box cho các API, có kiểm tra dữ liệu trả về và trạng thái database; đội QA manual làm black-box theo góc nhìn người dùng cuối, chạy các kịch bản nghiệp vụ từ tài liệu đặc tả khách hàng cung cấp.
Kết quả sau một quý: 60% lỗi được chặn ở lớp unit (white-box) trước khi lên môi trường test, 25% lỗi tích hợp bị bắt ở lớp API (grey-box), và 15% còn lại — chủ yếu là lỗi trải nghiệm và hiểu sai yêu cầu — do đội black-box phát hiện.
Bài học: Trong thực tế công nghiệp, ba góc nhìn không "đối đầu" mà được xếp lớp để bắt lỗi ở nhiều tầng khác nhau, mỗi tầng bắt loại lỗi mà tầng kia khó thấy.
Hướng dẫn từng bước
Khi đứng trước một tính năng cần kiểm thử, hãy chọn góc nhìn theo quy trình sau:
- Xác định bạn có quyền truy cập gì. Bạn được đọc source code không? Được xem database, log, cấu trúc API không? Câu trả lời này quyết định bạn đang ở góc nhìn nào. Không có code → black-box. Có code và biết đọc → có thể white-box. Có tài liệu kiến trúc/schema nhưng không đọc từng dòng → grey-box.
- Xác định cấp độ test. Nếu là unit test cho một hàm cụ thể → white-box là tự nhiên nhất. Nếu là kiểm thử hệ thống hoặc nghiệm thu (acceptance) → black-box. Nếu là integration/API → grey-box thường hiệu quả nhất.
- Với black-box: thu thập yêu cầu và đặc tả, liệt kê các lớp đầu vào hợp lệ và không hợp lệ, áp dụng Equivalence Partitioning và Boundary Value Analysis để tạo test case tối thiểu mà bao phủ tối đa hành vi.
- Với white-box: đọc code, vẽ sơ đồ luồng (control flow), liệt kê mọi nhánh và điều kiện, thiết kế test để mỗi nhánh được chạy ít nhất một lần, rồi đo coverage bằng công cụ (JaCoCo cho Java, Istanbul cho JavaScript, Coverage.py cho Python).
- Với grey-box: dựa vào hiểu biết kiến trúc để nhắm vào các điểm rủi ro (ràng buộc database, xử lý đồng thời, biên giới giữa các service), thiết kế test từ ngoài vào nhưng kiểm chứng kết quả ở nhiều lớp (giao diện + API response + bản ghi database + log).
- Kết hợp cả ba theo lớp. Đừng chọn một, bỏ hai. Một chiến lược trưởng thành luôn phối hợp: developer lo white-box ở tầng thấp, QA lo black-box ở tầng cao, SDET lo grey-box ở giữa.
Lỗi thường gặp & mẹo
Lỗi 1 — Nghĩ đây là ba loại test loại trừ nhau. Nhiều bạn junior nói "dự án em làm black-box nên không cần white-box". Sai. Đây là ba góc nhìn bổ sung. Câu trả lời phỏng vấn ghi điểm là: "Chúng phối hợp theo lớp, mỗi góc nhìn bắt một loại lỗi khác nhau."
Lỗi 2 — Đánh đồng black-box = manual, white-box = automation. Không đúng. Bạn hoàn toàn có thể tự động hóa test black-box (ví dụ Selenium/Playwright điều khiển giao diện mà không cần biết code bên trong). Ngược lại, white-box cũng có thể làm thủ công. Góc nhìn nói về mức độ biết code, không nói về thủ công hay tự động.
Lỗi 3 — Nghĩ white-box thì không cần đặc tả. Nguy hiểm. Nếu chỉ nhìn code, bạn sẽ test đúng những gì code làm — kể cả khi code làm sai so với yêu cầu. White-box giỏi bắt lỗi "code chạy sai logic của chính nó", nhưng dở bắt lỗi "thiếu hẳn một chức năng". Luôn đối chiếu với spec.
Lỗi 4 — Lẫn lộn grey-box với việc chỉ đọc log. Grey-box là dùng hiểu biết nội bộ để thiết kế test tốt hơn, không đơn thuần là xem log sau khi test xong.
Mẹo: Khi phỏng vấn, hãy neo câu trả lời vào một câu hỏi duy nhất: "Người test biết bao nhiêu về code bên trong?" — Không biết gì là đen, biết hết là trắng, biết một phần là xám. Đơn giản và không bao giờ sai.
Bài tập thực hành
Bài 1 — Phân loại góc nhìn. Với mỗi tình huống, xác định đó là black-box, white-box hay grey-box:
a) Bạn nhập ngày sinh 31/02/2026 vào form để xem hệ thống báo lỗi thế nào, không đọc code.
b) Developer viết test để đảm bảo cả nhánh if và else của hàm tính điểm đều được chạy.
c) Bạn biết API /login trả về JWT lưu ở bảng sessions, nên test đăng nhập rồi mở database kiểm tra bản ghi session được tạo đúng chưa.
Bài 2 — Thiết kế theo hai góc nhìn. Cho tính năng: "Mã giảm giá hợp lệ khi độ dài từ 6 đến 12 ký tự." Hãy (a) liệt kê test case theo góc nhìn black-box (gợi ý: dùng giá trị biên 5, 6, 12, 13 ký tự); (b) giả sử bạn được đọc code và thấy điều kiện if (len > 6 && len < 12), chỉ ra ngay hai giá trị mà code này xử lý sai so với yêu cầu.
Bài 3 — Tư duy grey-box. Bạn test chức năng "nạp tiền vào ví" và biết số dư lưu trong database. Hãy nghĩ ra một kịch bản grey-box mà một tester black-box thuần túy khó phát hiện (gợi ý: nghĩ về hai thao tác chạy song song, hoặc nạp số tiền cực lớn gây tràn kiểu dữ liệu).
Gợi ý đáp án Bài 1: a) black-box; b) white-box; c) grey-box. Bài 2b: code dùng > 6 và < 12 nên độ dài đúng 6 và đúng 12 (đều hợp lệ theo yêu cầu) lại bị từ chối — đó là hai giá trị biên bị xử lý sai.
Tóm tắt
Ba góc nhìn kiểm thử được phân biệt bởi một câu hỏi duy nhất: người test biết bao nhiêu về code bên trong.
- Black-box: không biết code, test dựa trên yêu cầu và hành vi, đóng vai người dùng. Mạnh ở việc bắt lỗi nghiệp vụ và thiếu chức năng; là nền của các kỹ thuật EP, BVA, Decision Table.
- White-box: biết toàn bộ code, test dựa trên cấu trúc, đo coverage theo câu lệnh/nhánh/đường đi. Mạnh ở lỗi logic ẩn; gắn với unit và integration test; cần kỹ năng lập trình.
- Grey-box: biết một phần nội bộ (kiến trúc, database, API), test từ ngoài nhưng nhắm mục tiêu và kiểm chứng nhiều lớp. Là góc nhìn thực tế nhất trong công việc hằng ngày, đặc biệt cho API và database testing.