Menu
ESC

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

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

Đang tải...

Test Case Design — chuẩn viết & template

Software Testing Fundamentals Bài 24/60

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

Bạn có bao giờ nhận được một test case kiểu này chưa: "Kiểm tra chức năng đăng nhập"? Đọc xong bạn chẳng biết phải bấm gì, nhập dữ liệu nào, và kết quả đúng phải ra sao. Nếu người viết ra nó nghỉ việc, cả team coi như phải đoán mò. Đó chính là lý do bài học hôm nay tồn tại.

Test case là đơn vị công việc nhỏ nhất mà một tester tạo ra và bàn giao. Nó giống như dòng code của một lập trình viên — nếu viết cẩu thả, cả hệ thống kiểm thử sẽ mục ruỗng từ bên trong. Một test case chuẩn cho phép bất kỳ ai trong team, kể cả người mới vào hôm qua, cầm lên và thực thi được ngay mà không cần hỏi lại. Nó là bằng chứng cho khách hàng thấy sản phẩm đã được kiểm tra những gì. Và khi có bug lọt lưới, chính bộ test case là nơi đầu tiên người ta soi lại để xem "tại sao chúng ta không bắt được lỗi này".

Ở bài này, chúng ta tập trung hoàn toàn vào cách viết một test case cho đúng chuẩn và một template dùng được ngay. Chúng ta sẽ không bàn về kỹ thuật thiết kế (Equivalence Partitioning, Boundary Value...) vì đó là các bài riêng — ở đây bạn học cách trình bày, cấu trúc và diễn đạt một test case sao cho chuyên nghiệp, rõ ràng và dễ bảo trì. Nắm vững kỹ năng này, bạn sẽ tự tin ở bất kỳ công ty nào, bởi viết test case tốt là "chữ ký nghề nghiệp" của một QA nghiêm túc.

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

Test case là gì và gồm những gì

Test case là một tập hợp các điều kiện, dữ liệu đầu vào, các bước thực hiện và kết quả mong đợi, được thiết kế để kiểm tra xem một tính năng có hoạt động đúng như yêu cầu hay không. Một test case tốt luôn trả lời được ba câu hỏi: Kiểm tra cái gì? Làm như thế nào? Đúng thì phải ra sao?

Dưới đây là cấu trúc tối thiểu mà bất kỳ test case chuyên nghiệp nào cũng cần có:

Field (Trường)Mô tảVí dụ
Test Case IDMã định danh duy nhất, dễ tra cứuTC-LOGIN-001
TitleTiêu đề ngắn gọn nói rõ mục tiêu kiểm thửĐăng nhập với email hợp lệ và mật khẩu đúng
PreconditionĐiều kiện tiên quyết trước khi chạyTài khoản user@shopee.vn đã tồn tại và được kích hoạt
Test StepsCác bước thực hiện, đánh số rõ ràng1. Mở trang đăng nhập...
Test DataDữ liệu cụ thể dùng để nhậpEmail: user@shopee.vn / Pass: Abc@12345
Expected ResultKết quả mong đợi, cụ thể và đo đượcChuyển đến trang chủ, hiển thị "Xin chào"
Actual ResultKết quả thực tế khi chạy (điền lúc thực thi)(để trống ban đầu)
StatusPass / Fail / Blocked / Not RunPass
Một số trường bổ sung thường gặp trong thực tế: Priority (mức ưu tiên chạy — cao/trung bình/thấp), Severity đề xuất, Test Type (Functional, UI, Security...), Author (người viết), Requirement ID (liên kết đến yêu cầu gốc để truy vết — traceability).

Nguyên tắc vàng khi viết test case

Có bốn tính chất mà một test case đạt chuẩn phải thỏa mãn, tôi gọi tắt là bộ tiêu chí CADT:

  • Clear (Rõ ràng): Mỗi bước chỉ mô tả một hành động. Không viết "đăng nhập rồi vào giỏ hàng và thanh toán" trong một dòng.
  • Atomic (Đơn nhất): Một test case chỉ kiểm tra một mục tiêu. Đừng nhét năm kịch bản vào một test case, vì khi Fail bạn sẽ không biết bước nào hỏng.
  • Deterministic (Xác định): Cùng một đầu vào, chạy 100 lần phải ra cùng một kết quả. Tránh dữ liệu ngẫu nhiên không kiểm soát.
  • Traceable (Truy vết được): Mỗi test case gắn với một yêu cầu (requirement) cụ thể, để khi yêu cầu thay đổi bạn biết ngay test case nào cần cập nhật.

Kết quả mong đợi phải "đo được"

Đây là chỗ tân binh hay mắc lỗi nhất. "Hệ thống hoạt động bình thường" không phải là expected result — vì "bình thường" là bao nhiêu? Kết quả mong đợi phải cụ thể đến mức người kiểm tra chỉ cần nhìn màn hình là kết luận được Pass hay Fail: "Hiển thị thông báo màu đỏ 'Email hoặc mật khẩu không đúng' ngay dưới ô nhập, người dùng vẫn ở lại trang đăng nhập."

Tình huống thực tế

Tình huống 1 — Test case mơ hồ khiến bug lọt ra production tại một sàn TMĐT

Một công ty thương mại điện tử tại TP.HCM (gọi là ShopViet) có test case cho chức năng áp mã giảm giá chỉ ghi vỏn vẹn: "Test mã giảm giá — kết quả: giảm giá đúng". Bạn tester mới tên Linh nhận ca kiểm thử, cô nhập mã SALE50, thấy đơn hàng được giảm, đánh Pass và đi tiếp.

Vấn đề là mã SALE50 được thiết kế "giảm 50% tối đa 100.000đ", nhưng hệ thống lại giảm thẳng 50% không giới hạn. Với đơn 5 triệu, khách được giảm 2,5 triệu thay vì 100.000đ. Linh không sai — cô thấy "được giảm" nên đánh Pass, vì test case không hề nói rõ mức trần. Trong đợt sale 12/12, lỗ hổng này khiến ShopViet thiệt hại gần 80 triệu đồng chỉ trong bốn tiếng.

Bài học: Test case phải ghi expected result đo được: "Đơn 5.000.000đ, áp mã SALE50 → số tiền giảm hiển thị đúng 100.000đ, tổng thanh toán 4.900.000đ." Khi con số cụ thể nằm sẵn trong test case, dù ai chạy cũng bắt được bug ngay lập tức.

Tình huống 2 — Team QA của một startup fintech chuẩn hóa template và tăng tốc onboarding

Một startup ví điện tử ở Hà Nội có 6 QA, mỗi người viết test case theo một kiểu: người dùng Excel, người ghi trên Notion, người viết cả đoạn văn dài không xuống dòng. Khi có bạn mới vào, phải mất hai tuần chỉ để hiểu "phong cách" của từng đồng nghiệp. Tệ hơn, khi audit để xin chứng nhận bảo mật, đối tác kiểm toán không đọc nổi bộ test case và yêu cầu làm lại.

Team lead quyết định áp một template thống nhất với đủ 8 trường chuẩn (ID, Title, Precondition, Steps, Data, Expected, Actual, Status), kèm quy ước đặt ID theo module: TC-KYC-001, TC-TOPUP-014... Sau ba tháng, thời gian onboarding một QA mới giảm từ hai tuần xuống còn ba ngày, và tỷ lệ test case bị hiểu sai khi bàn giao giảm rõ rệt. Quan trọng hơn, khi tích hợp vào công cụ quản lý như TestRail, dữ liệu vào gọn gàng vì mọi test case đều cùng khuôn.

Bài học: Template không phải là thủ tục hành chính. Nó là ngôn ngữ chung giúp cả team giao tiếp không cần giải thích, và là điều kiện sống còn khi công ty lớn lên hoặc cần audit.

Tình huống 3 — Test case "nhiều mục tiêu" gây khó truy lỗi tại một dự án gia công phần mềm

Một công ty outsourcing ở Đà Nẵng làm dự án cho khách Nhật. Một QA viết test case đăng ký tài khoản gồm 15 bước liền mạch: nhập thông tin, upload ảnh CMND, xác thực OTP, tạo mật khẩu, đăng nhập lần đầu, cập nhật hồ sơ... tất cả trong một test case duy nhất tên "Đăng ký tài khoản đầy đủ".

Khi chạy, test case Fail ở đâu đó giữa chừng. Report gửi về khách Nhật chỉ ghi "TC-REG-001: Fail". Khách hỏi lại "Fail ở bước nào?", team phải chạy lại từ đầu mất 40 phút để tái hiện. Lặp lại vài lần, khách mất kiên nhẫn và đánh giá chất lượng QA thấp.

Sau đó team tách thành các test case atomic: TC-REG-001 (nhập thông tin cơ bản), TC-REG-002 (upload CMND), TC-REG-003 (xác thực OTP)... Giờ khi Fail, report chỉ rõ "TC-REG-003 Fail — OTP hết hạn sau 60s nhưng hệ thống vẫn báo hợp lệ". Khách nắm bug trong 30 giây.

Bài học: Nguyên tắc Atomic không chỉ là lý thuyết — nó trực tiếp quyết định tốc độ debug và uy tín của team với khách hàng.

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

Đây là quy trình 7 bước để viết một test case chuẩn từ đầu:

Bước 1 — Xác định mục tiêu kiểm thử. Đọc yêu cầu (requirement/user story) và chốt: test case này kiểm tra chính xác điều gì? Một mục tiêu duy nhất. Ví dụ: "Xác nhận người dùng đăng nhập được với thông tin đúng."

Bước 2 — Đặt Test Case ID có quy tắc. Dùng công thức TC-<MODULE>-<SỐ>. Ví dụ TC-LOGIN-001. Quy ước này giúp tìm kiếm, lọc và trao đổi cực nhanh. Đừng bao giờ dùng ID kiểu "test1, test2".

Bước 3 — Viết Title theo công thức. Một title tốt thường có dạng: [Hành động] + [đối tượng] + [điều kiện]. Ví dụ: "Đăng nhập với email hợp lệ và mật khẩu đúng" hoặc "Áp mã giảm giá đã hết hạn". Chỉ đọc title là hình dung được kịch bản.

Bước 4 — Ghi Precondition. Liệt kê những gì phải có sẵn: tài khoản đã tạo, đang ở màn hình nào, dữ liệu nào đã tồn tại. Nếu bỏ qua bước này, người chạy test sẽ vấp ngay từ đầu.

Bước 5 — Viết Test Steps đánh số, mỗi bước một hành động. Dùng động từ hành động rõ ràng: "Nhập...", "Bấm nút...", "Chọn...". Ví dụ:

  • Mở trình duyệt, truy cập trang /login.
  • Nhập email vào ô "Email".
  • Nhập mật khẩu vào ô "Mật khẩu".
  • Bấm nút "Đăng nhập".
Bước 6 — Điền Test Data cụ thể. Không viết chung chung "email hợp lệ", hãy ghi hẳn user@vietnamcos.com. Dữ liệu càng cụ thể, test case càng dễ tái hiện.

Bước 7 — Viết Expected Result đo được. Mô tả trạng thái cuối cùng có thể quan sát: "Chuyển đến /dashboard, góc trên phải hiển thị 'Xin chào, Khang', không có thông báo lỗi."

Sau khi viết xong, hãy tự "đọc thử như người lạ": nếu bạn đưa test case này cho người chưa biết gì về dự án mà họ vẫn chạy được, bạn đã thành công.

Dưới đây là một test case hoàn chỉnh theo template để bạn tham chiếu:

TrườngNội dung
IDTC-LOGIN-002
TitleĐăng nhập thất bại với mật khẩu sai
PriorityCao
PreconditionTài khoản user@vietnamcos.com đã tồn tại và kích hoạt
Steps1. Truy cập /login 2. Nhập email user@vietnamcos.com 3. Nhập mật khẩu SaiRoi123 4. Bấm "Đăng nhập"
Test DataEmail đúng, mật khẩu sai như trên
Expected ResultHiển thị thông báo đỏ "Email hoặc mật khẩu không đúng" dưới form; người dùng vẫn ở trang /login; ô mật khẩu được xóa trắng
Actual Result(điền khi chạy)
Status(Not Run)

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

Lỗi 1 — Expected result mơ hồ. Viết "hệ thống chạy đúng" là vô nghĩa. Mẹo: luôn tự hỏi "đúng nghĩa là màn hình hiển thị gì, con số bao nhiêu, chuyển đến trang nào?".

Lỗi 2 — Nhồi nhiều mục tiêu vào một test case. Khi Fail sẽ không biết lỗi ở đâu. Mẹo: mỗi test case một mục tiêu; nếu title có chữ "và" nối hai hành động độc lập, hãy cân nhắc tách đôi.

Lỗi 3 — Bỏ quên precondition. Người chạy không có dữ liệu để bắt đầu. Mẹo: trước khi viết steps, hỏi "muốn chạy bước 1 thì cần có sẵn cái gì?".

Lỗi 4 — Bước quá to hoặc quá vụn. "Đăng nhập vào hệ thống" là một bước gộp nhiều thao tác; ngược lại "di chuyển chuột đến ô email" thì quá vụn. Mẹo: một bước = một hành động người dùng có ý nghĩa.

Lỗi 5 — ID lộn xộn, không quy tắc. Khiến bộ test case thành mớ bòng bong khi lên đến hàng nghìn cái. Mẹo: chốt quy ước đặt ID ngay từ test case đầu tiên của dự án.

Lỗi 6 — Chỉ viết happy path. Nhiều bạn chỉ viết trường hợp "mọi thứ đúng" mà quên các case tiêu cực (nhập sai, để trống, dữ liệu bất thường). Mẹo: với mỗi tính năng, viết ít nhất một positive và một vài negative case.

Mẹo bảo trì: dùng "shared steps" cho các bước lặp lại (như đăng nhập) để khi flow thay đổi bạn chỉ sửa một chỗ. Và luôn ghi Author + ngày tạo để dễ hỏi lại khi cần.

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

Bài 1 — Sửa test case tệ. Cho test case sau: "Title: Test tìm kiếm. Steps: Tìm sản phẩm. Expected: Ra kết quả đúng." Hãy viết lại thành test case chuẩn với đủ 8 trường, dữ liệu cụ thể (ví dụ tìm "son môi 3CE"), và expected result đo được.

Bài 2 — Viết bộ test case cho chức năng đăng ký. Chọn tính năng đăng ký tài khoản của một website bạn hay dùng (Shopee, Tiki, Grab...). Viết tối thiểu 5 test case gồm: 1 positive (đăng ký thành công) và 4 negative (email sai định dạng, mật khẩu quá ngắn, để trống trường bắt buộc, email đã tồn tại). Áp dụng đúng quy tắc đặt ID và nguyên tắc Atomic.

Bài 3 — Tự review. Đưa bộ test case ở Bài 2 cho một người bạn không rành kỹ thuật đọc và thử "chạy" theo từng bước. Ghi lại chỗ nào họ bối rối, rồi sửa lại cho rõ ràng hơn. Đây chính là cách kiểm tra tính Clear trong thực tế.

Tóm tắt

Test case là đơn vị công việc cốt lõi của mọi QA, và viết test case chuẩn chính là "chữ ký nghề nghiệp" của bạn. Một test case đạt chuẩn cần đủ cấu trúc tối thiểu — ID, Title, Precondition, Steps, Test Data, Expected Result, Actual Result, Status — và tuân theo bốn nguyên tắc CADT: Clear, Atomic, Deterministic, Traceable.

Điều quan trọng nhất cần khắc cốt ghi tâm: Expected Result phải đo được, mỗi test case chỉ kiểm tra một mục tiêu, và ID phải theo quy tắc nhất quán. Ba câu chuyện thực tế — từ vụ mã giảm giá gây thiệt hại 80 triệu, đến team fintech rút ngắn onboarding, đến dự án outsourcing Đà Nẵng cải thiện tốc độ debug — đều cho thấy chất lượng test case ảnh hưởng trực tiếp đến tiền bạc, thời gian và uy tín.

Hãy dùng template trong bài làm khuôn mẫu cho mọi test case bạn viết, và luôn tự "đọc như người lạ" trước khi bàn giao. Khi bạn viết test case tốt đến mức ai cũng chạy được mà không cần hỏi, bạn đã trở thành một QA chuyên nghiệp thực thụ.