Product Management
Đăng nhập
ESC

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

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

AI-Assisted Test Generation

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

Cách đây vài năm, khi tôi phỏng vấn ứng viên vị trí Automation Engineer tại một công ty fintech ở TP.HCM, câu hỏi kinh điển là "Bạn viết được bao nhiêu test case một ngày?". Bây giờ câu hỏi đó gần như vô nghĩa. Một kỹ sư biết dùng LLM (Large Language Model — mô hình ngôn ngữ lớn như ChatGPT, Claude, GitHub Copilot) có thể phác thảo 50 test case trong 15 phút, thời gian còn lại dành để làm cái mà máy không làm được: đánh giá độ đúng, cắt bỏ case thừa, và thiết kế những kịch bản mà con người mới nghĩ ra.

Đây chính là lằn ranh phân chia SDET (Software Development Engineer in Test) của năm 2026. Không phải "AI thay thế tester", mà là "tester biết dùng AI thay thế tester không biết dùng". Bài này không dạy bạn thần thánh hóa AI, cũng không dạy bạn sợ nó. Tôi muốn bạn học cách dùng LLM như một cộng sự junior cực nhanh nhưng cực ẩu — bạn giao việc, nó làm ngay, và bạn phải review kỹ trước khi merge.

Điều quan trọng nhất tôi muốn bạn ghi nhớ ngay từ đầu: AI sinh ra test rất giỏi, nhưng nó không hiểu nghiệp vụ của bạn, không biết bug nào từng xảy ra trong quá khứ, và nó rất hay bịa (hallucinate) API không tồn tại. Trách nhiệm về chất lượng vẫn là của bạn. Hiểu điều này rồi, chúng ta bắt đầu.

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

AI-Assisted Test Generation là gì

Hiểu đơn giản, đây là việc dùng LLM để hỗ trợ tạo ra các artifact liên quan đến test: từ danh sách test case (dạng văn bản), đến code test cụ thể (Selenium, Cypress, pytest, REST Assured...), đến dữ liệu test, và cả việc giải thích một đoạn test khó hiểu.

Có bốn nhóm use case chính mà bạn sẽ dùng hằng ngày:

  • Generate test case từ spec/requirement — bạn đưa mô tả API hoặc user story, AI liệt kê các kịch bản cần test (happy path, edge case, negative case).
  • Generate test code từ test case — bạn có sẵn kịch bản, AI viết code thực thi bằng framework bạn chọn.
  • Generate test từ code có sẵn — dán một hàm/class, AI đề xuất unit test bao phủ các nhánh logic.
  • Refactor & giải thích test — dán test flaky hoặc khó hiểu, AI đề xuất cách sửa hoặc diễn giải.

Ba cấp độ tích hợp AI vào quy trình

Cấp 1 — Chat-based (ChatGPT, Claude qua web/app): bạn copy-paste thủ công. Linh hoạt, tốt cho việc brainstorm test case và thiết kế.

Cấp 2 — IDE-integrated (GitHub Copilot, Cursor, Codeium ngay trong VS Code/IntelliJ): AI gợi ý code inline khi bạn gõ. Nhanh nhất cho việc viết code test lặp đi lặp lại.

Cấp 3 — Agent/tool-based (các công cụ chuyên như CodiumAI/Qodo, Testim, mabl, hoặc self-hosted script gọi API): AI tự đọc codebase, tự sinh test, thậm chí tự chạy và tự sửa. Mạnh nhưng cần kiểm soát chặt.

Nguyên tắc "AI đề xuất, người quyết định"

Đây là mô hình tinh thần (mental model) tôi muốn bạn khắc cốt ghi tâm. Vòng lặp làm việc lành mạnh là:

Con người mô tả bối cảnh → AI sinh nháp → Con người review & sửa → Chạy thử → Feedback lại cho AI.

Nếu bạn bỏ bước review, bạn không tiết kiệm được thời gian đâu — bạn chỉ đẩy nợ kỹ thuật (technical debt) sang tương lai, và nợ đó thường phát nổ đúng lúc gần release.

Prompt engineering cho tester

Chất lượng output phụ thuộc gần như hoàn toàn vào chất lượng prompt. Một prompt tốt cho việc sinh test cần có bốn thành phần: Bối cảnh (đây là hệ thống gì, dùng framework nào), Đầu vào cụ thể (spec, code, hoặc test case), Yêu cầu định dạng (viết bằng pytest, dùng AAA pattern, đặt tên tiếng Anh), và Ràng buộc (đừng bịa API, chỉ dùng thư viện X, cover cả case tiếng Việt có dấu).

Tình huống thực tế

Ví dụ 1 — Startup fintech Cần Thơ sinh test case cho API nạp tiền

Một startup ví điện tử nhỏ ở Cần Thơ (khoảng 12 người, đội QA chỉ có 2 bạn) cần test endpoint POST /api/v1/wallet/topup trước sprint review. Bạn QA lead dán spec vào Claude: endpoint nhận amount (VND, tối thiểu 10.000, tối đa 20.000.000), payment_method (momo/vnpay/bank), user_id. Prompt yêu cầu: "Liệt kê test case dưới dạng bảng, phân nhóm happy path / boundary / negative / security, có cột mô tả và kết quả mong đợi."

AI trả về 34 test case trong 20 giây, bao gồm cả những case bạn QA suýt quên: nạp đúng 9.999đ (dưới ngưỡng), nạp số âm, amount dạng chuỗi "10000", concurrent topup cùng lúc (race condition), và cả SQL injection ở user_id. Bạn QA giữ lại 28 case, bỏ 6 case không liên quan tới nghiệp vụ (AI đề xuất test đổi tiền tệ USD trong khi ví này chỉ hỗ trợ VND).

Bài học: AI xuất sắc ở việc "quét sạch không gian đầu vào" — nó không mệt, không quên boundary. Nhưng nó bịa ra tính năng USD vì trong training data các ví điện tử thường đa tiền tệ. Con người phải cắt bỏ dựa trên hiểu biết nghiệp vụ thật.

Ví dụ 2 — Đội Selenium ở Hà Nội dùng Copilot sinh Page Object

Một công ty outsourcing ở Hà Nội có suite Selenium 400 test cho một trang thương mại điện tử. Mỗi khi client thêm trang mới, viết Page Object Model thủ công mất cả buổi. Họ bật GitHub Copilot trong IntelliJ, viết comment mô tả cấu trúc trang và tên các element, Copilot gợi ý toàn bộ class Page Object với các phương thức clickAddToCart(), getPrice()...

Ban đầu năng suất tăng vọt, nhưng sau hai tuần họ gặp vấn đề: Copilot toàn gợi ý locator kiểu XPath tuyệt đối dài loằng ngoằng (/html/body/div[3]/div[2]/...) vì nó không thấy được HTML thật, chỉ đoán. Những locator này gãy ngay khi UI đổi. Đội phải thêm bước: cung cấp cho AI đoạn HTML thật của element, và ra quy ước "ưu tiên locator theo data-testid hoặc CSS ngắn". Sau khi chỉnh, tỉ lệ locator hỏng giảm rõ rệt.

Bài học: AI viết structure (khung code) rất tốt nhưng đoán chi tiết (locator cụ thể) rất tệ khi thiếu ngữ cảnh thật. Hãy đưa cho nó dữ liệu thật, đừng để nó tự bịa.

Ví dụ 3 — Sinh unit test cho code Java tại một ngân hàng số

Một ngân hàng số ở Singapore có phục vụ thị trường Việt Nam yêu cầu coverage tối thiểu 80% cho module tính lãi suất. Team dùng công cụ CodiumAI/Qodo tích hợp IDE, chỉ vào class InterestCalculator và bảo "sinh JUnit 5 test cover mọi nhánh". Công cụ sinh ra 15 test, đẩy coverage từ 62% lên 91%.

Nhưng khi review, tech lead phát hiện một điều nguy hiểm: nhiều test được viết theo kiểu "test khớp với code hiện tại" chứ không "test theo đúng yêu cầu nghiệp vụ". Cụ thể, code có bug làm tròn (round down thay vì round half-up theo quy định ngân hàng), và AI sinh test khẳng định luôn kết quả sai đó là đúng. Test pass 100% nhưng bug vẫn còn nguyên. Team phải rà lại các assertion quan trọng đối chiếu với tài liệu nghiệp vụ.

Bài học: Đây là cạm bẫy nguy hiểm nhất của AI-generated unit test — nó test "code đang làm gì" chứ không phải "code nên làm gì". Với logic nghiệp vụ quan trọng (tiền bạc, quyền hạn), assertion phải do con người xác nhận đối chiếu spec.

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

Tôi sẽ hướng dẫn bạn quy trình thực chiến để sinh test case và test code cho một API, dùng chat-based LLM (áp dụng được cho cả ChatGPT lẫn Claude).

Bước 1 — Chuẩn bị ngữ cảnh đầy đủ. Trước khi mở AI, gom lại: spec/tài liệu API (endpoint, tham số, ràng buộc), framework mục tiêu (ví dụ Python requests + pytest), và các quy ước của team (naming, cách quản lý test data). Càng nhiều ngữ cảnh, output càng ít phải sửa.

Bước 2 — Sinh test case ở dạng văn bản trước, đừng nhảy thẳng vào code. Prompt mẫu:

> "Bạn là senior QA. Tôi có endpoint POST /api/orders nhận product_id (int), quantity (1-100), coupon_code (optional). Liệt kê test case dưới dạng bảng Markdown, phân nhóm happy path / boundary / negative / security. Mỗi case có: mô tả, input, expected result. KHÔNG viết code. KHÔNG bịa thêm tham số không có trong spec."

Câu "không bịa thêm tham số" cực kỳ quan trọng — nó kéo AI về đúng phạm vi.

Bước 3 — Review danh sách case như một con người. Đọc từng dòng, tự hỏi: Case này có đúng nghiệp vụ không? Có thiếu kịch bản đặc thù Việt Nam không (ví dụ coupon chỉ áp dụng cho đơn trên 500.000đ, hay tên sản phẩm có dấu tiếng Việt)? Xóa case thừa, thêm case AI không biết.

Bước 4 — Sinh code từ danh sách case đã chốt. Giờ mới đưa danh sách đã duyệt vào và yêu cầu:

> "Viết pytest cho các test case sau, dùng thư viện requests, base_url lấy từ biến môi trường, mỗi test một hàm với tên rõ nghĩa, dùng @pytest.mark.parametrize cho các case boundary. KHÔNG dùng thư viện ngoài requestspytest."

Bước 5 — Chạy và đối chiếu. Chạy suite. Đừng tin test nào pass ngay lần đầu — kiểm tra ít nhất một test negative có thật sự fail khi bạn cố tình phá endpoint không. Test luôn xanh có thể là test rỗng.

Bước 6 — Feedback vòng lặp. Khi có test lỗi hoặc assertion sai, dán lỗi lại cho AI: "Test này fail với thông báo X, đây là response thật, hãy sửa assertion." Lặp cho đến khi ổn.

Bước 7 — Đưa vào review của người khác. Test do AI sinh vẫn phải qua code review như code người viết. Đây là chốt chặn cuối.

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

Bịa API/method không tồn tại (hallucination). AI rất hay gọi phương thức nghe hợp lý nhưng không có trong thư viện của bạn, ví dụ driver.waitForElement() trong Selenium Java (không tồn tại). Mẹo: luôn chạy thử ngay, và cung cấp phiên bản thư viện cụ thể trong prompt ("Selenium 4.x, dùng WebDriverWait").

Assertion "dối trá" — test luôn pass. Như ví dụ ngân hàng, AI có thể sinh assertion khớp với hành vi hiện tại thay vì hành vi đúng. Mẹo: với logic quan trọng, tự viết assertion, chỉ nhờ AI viết phần setup và teardown.

Test quá phụ thuộc chi tiết (brittle). AI hay hard-code locator, ID, timestamp. Mẹo: yêu cầu rõ "dùng locator ổn định theo data-testid, không hard-code dữ liệu động".

Lộ dữ liệu nhạy cảm. Đừng bao giờ dán token thật, mật khẩu production, hay PII (thông tin cá nhân khách hàng) vào chat AI công cộng. Mẹo: dùng dữ liệu giả, ẩn danh trước khi paste; với dự án nhạy cảm, cân nhắc LLM chạy nội bộ (self-hosted).

Bỏ quên đặc thù Việt Nam. AI thường quên test tên có dấu tiếng Việt, số điện thoại định dạng VN, hay luồng thanh toán MoMo/VNPay. Mẹo: liệt kê rõ các ràng buộc bản địa trong prompt.

Sinh hàng loạt rồi merge mù. Cám dỗ lớn nhất là AI sinh 100 test, bạn thấy xanh hết và merge luôn. Mẹo: chất lượng hơn số lượng — 20 test được review kỹ hơn 100 test không ai đọc.

Mẹo vàng: Hãy coi AI như junior nhanh nhưng ẩu. Bạn sẽ không bao giờ merge PR của junior mà không đọc, thì cũng đừng làm vậy với AI.

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

  • Sinh và tinh chỉnh test case. Chọn một API bất kỳ bạn từng làm (hoặc dùng POST /login với email, password). Viết một prompt đầy đủ 4 thành phần (bối cảnh, đầu vào, định dạng, ràng buộc) và yêu cầu AI liệt kê test case. Sau đó tự tay thêm 3 case đặc thù Việt Nam mà AI bỏ sót.
  • So sánh chất lượng theo prompt. Lấy cùng một đoạn code (một hàm tính giảm giá), hỏi AI sinh unit test hai lần: lần một prompt cụt lủn ("viết test cho hàm này"), lần hai prompt chi tiết (framework, pattern, ràng buộc cover cả case số âm và null). Ghi lại khác biệt về số case và chất lượng assertion.
  • Săn hallucination. Yêu cầu AI viết một test Selenium hoặc Cypress, rồi rà từng dòng tìm ít nhất một method/API mà bạn nghi nó bịa. Tra tài liệu chính thức để xác nhận. Đây là kỹ năng phản xạ bạn phải luyện.
  • Viết checklist review. Dựa trên bài này, tự soạn một checklist 6–8 mục để review mọi test do AI sinh trước khi merge (ví dụ: "đã kiểm tra không bịa API chưa", "assertion đối chiếu spec chưa", "có test negative thật sự fail không"). Dùng nó cho lần dùng AI tiếp theo.

Tóm tắt

AI-Assisted Test Generation không phải là phép màu thay thế tester, mà là công cụ tăng tốc mạnh mẽ khi được dùng đúng. Bốn use case cốt lõi bạn sẽ dùng thường xuyên: sinh test case từ spec, sinh code từ test case, sinh test từ code có sẵn, và refactor/giải thích test. Ba cấp độ tích hợp đi từ chat-based, IDE-integrated, đến agent-based, mỗi cấp mạnh và rủi ro khác nhau.

Ba bài học từ thực tế nhắc bạn: AI quét boundary cực giỏi nhưng bịa nghiệp vụ (ví ở Cần Thơ), AI viết khung code tốt nhưng đoán chi tiết tệ khi thiếu ngữ cảnh thật (Selenium Hà Nội), và AI hay test "code đang làm gì" thay vì "code nên làm gì" (ngân hàng số). Nguyên tắc bao trùm tất cả: AI đề xuất, con người quyết định. Chất lượng prompt quyết định chất lượng output, và không có test nào do AI sinh được phép merge mà chưa qua review của con người. Nắm chắc điều này, bạn không chỉ dùng AI để làm nhanh hơn — bạn dùng nó để làm tốt hơn.

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