·

Tiếng Việt: Writing effective prompts for QA

Writing effective prompts for QA

Biết lý thuyết về token, context window, role framing là một chuyện — biết ngồi viết một prompt cụ thể lúc 4 giờ chiều thứ Sáu để kịp phân tích một bug production là chuyện khác. Bài này đi thẳng vào kỹ năng thực chiến: công thức viết prompt, cách chẩn đoán prompt yếu, khi nào nên cụ thể - khi nào nên mở, và quan trọng nhất — cách sửa khi AI trả lời "sai" hoặc "dở".

Điều Gì Làm Nên Một QA Prompt Tốt — Task, Context, Constraint, và Expected Output?

Bốn Thành Phần Cốt Lõi

Một prompt QA tốt, dù ngắn dù dài, luôn có đủ bốn thành phần sau — thiếu một trong bốn là nguyên nhân phổ biến nhất khiến output không dùng được:

  1. Task — hành động cụ thể bạn muốn AI làm (viết, phân tích, so sánh, tóm tắt, đề xuất...). Không phải "giúp tôi về cái này" mà phải là một động từ hành động rõ ràng.
  2. Context — dữ liệu nền để AI hiểu đúng bối cảnh (requirement, code, log, test case cũ). Đây là phần dễ thiếu nhất vì QA engineer thường nghĩ "AI chắc hiểu" nhưng AI không có quyền truy cập vào kiến thức nghiệp vụ nằm trong đầu bạn.
  3. Constraint — ràng buộc về phạm vi, số lượng, những gì loại trừ. Thiếu constraint là nguyên nhân số 1 khiến AI trả lời "đúng nhưng không phải điều tôi cần" (ví dụ bạn hỏi test API nhưng nhận về cả UI test).
  4. Expected output — hình dạng cụ thể của kết quả mong muốn (bảng, JSON, danh sách có đánh số, độ dài). Thiếu phần này khiến bạn phải làm thêm bước "định dạng lại" tốn thời gian hơn cả lúc viết prompt.

Chẩn Đoán Prompt Yếu

Cách nhanh nhất để tự kiểm tra một prompt trước khi gửi: đọc lại và tự hỏi thiếu thành phần nào trong 4 thành phần trên. Ví dụ prompt yếu điển hình:

"Viết test case cho tính năng login."

Phân tích: có Task ("viết test case"), nhưng thiếu Context (login theo cơ chế gì — password, OTP, SSO?), thiếu Constraint (bao nhiêu test case, mức API hay UI?), thiếu Expected output (định dạng gì?). Kết quả: AI sẽ tự "bịa" các giả định để lấp đầy 3 phần thiếu — và giả định của AI hiếm khi khớp với điều bạn thực sự cần.

Dấu hiệu nhận biết prompt yếu trong thực tế (trước khi cả gửi đi):
- Câu prompt có thể áp dụng cho 10 tình huống khác nhau mà vẫn "đúng ngữ pháp" — nghĩa là nó chưa đủ cụ thể cho tình huống của bạn.
- Bạn không thể tự trả lời câu hỏi "AI sẽ biết dừng ở đâu?" — nếu không có giới hạn rõ, AI có thể viết 3 test case hoặc 30 test case, cả hai đều "hợp lý" với prompt mơ hồ.
- Bạn không hình dung được rõ định dạng bảng/JSON/danh sách mà bạn muốn nhận lại — nếu bạn còn mơ hồ, AI càng mơ hồ hơn.

Một Mẫu QA Prompt Tối Thiểu Nhưng Đủ Dùng

Không phải mọi prompt cần dài dòng. Đây là một template tối thiểu (minimal viable) đủ 4 thành phần, dùng được cho hầu hết task QA hàng ngày:

[Task] <động từ hành động> <đối tượng cụ thể>
[Context] <thông tin nền cần thiết — requirement/code/log, dán trực tiếp hoặc tóm tắt>
[Constraint] <giới hạn phạm vi + số lượng + loại trừ>
[Expected output] <định dạng cụ thể>

Ví dụ áp dụng thực tế:

[Task] Viết test case kiểm thử tính năng quên mật khẩu (forgot password) qua email.

[Context] Flow: User nhập email → hệ thống gửi link reset (hiệu lực 30 phút) →
User click link → nhập password mới → xác nhận.

[Constraint] 8 test case, chỉ mức API, bao gồm bắt buộc: link hết hạn, email không
tồn tại trong hệ thống, password mới không đạt policy độ mạnh tối thiểu.

[Expected output] Bảng: ID | Test Case | Steps | Expected Result | Priority

Ví Dụ Đối Chiếu: Prompt Đầy Đủ vs. Prompt Tối Thiểu Cho Cùng Một Task

Prompt tối thiểu (nhanh, dùng cho task quen thuộc lặp lại):

Viết 5 test case API cho endpoint GET /api/orders/{id}, gồm happy path, order
không tồn tại, và không có quyền xem order của người khác. Bảng markdown:
ID | Test Case | Expected Result.

Prompt đầy đủ (dùng cho task quan trọng, độ rủi ro cao, hoặc lần đầu làm với AI):

[Role] Bạn là Senior QA Engineer chuyên API testing cho hệ thống có yêu cầu bảo mật
cao (fintech).

[Context] Endpoint: GET /api/orders/{id}
Authorization: Bearer token, order chỉ thuộc về user tạo ra nó (owner-based access).
Response 200 trả về chi tiết order, 404 nếu order không tồn tại, 403 nếu user không
phải owner của order.

[Constraint] Viết 10 test case, mức API only. Bắt buộc có:
- 2 test case về broken object level authorization (IDOR) — cố truy cập order
  của user khác bằng cách đổi {id}
- 1 test case về token hết hạn/không hợp lệ
- 1 test case về order id không tồn tại trong hệ thống
Không viết test case về performance/load.

[Format] Bảng: ID | Test Case | Preconditions | Steps | Expected Result | Priority

[Self-check] Rà lại: đã có đủ test case cho cả 3 loại response code (200/403/404)
chưa — nếu thiếu, bổ sung.

Sự khác biệt không chỉ ở độ dài — prompt đầy đủ chủ động dẫn AI vào đúng loại rủi ro nghiêm trọng nhất (IDOR — Insecure Direct Object Reference, lỗi kiểm soát truy cập phổ biến và nguy hiểm) mà prompt tối thiểu có thể bỏ sót hoàn toàn nếu AI không tự nghĩ đến.

Mẹo: Giữ một file "prompt template" riêng cho các task lặp lại (sinh test case API, phân tích bug, viết test plan...) — đừng viết lại từ đầu mỗi lần. Chỉ cần đổi phần Context và Constraint, giữ nguyên khung Task/Format đã được kiểm chứng hiệu quả.

Cách Viết Prompt Cho Sinh Test Case, Phân Tích Bug, và Lập Kế Hoạch Exploratory Testing?

Sinh Test Case

Với sinh test case, điểm mấu chốt là cung cấp business rule cụ thể, không chỉ mô tả chức năng chung. AI có thể viết test case "đúng cú pháp" từ một mô tả mơ hồ, nhưng chỉ viết được test case "đúng giá trị" (catch được bug thật) khi biết rõ ràng buộc nghiệp vụ:

Tính năng: Áp dụng mã giảm giá (voucher) khi thanh toán.
Business rule:
- Mỗi voucher chỉ dùng được 1 lần/user
- Voucher có ngày hết hạn, giá trị tối thiểu đơn hàng để áp dụng
- Không áp dụng đồng thời 2 voucher
- Giảm giá không được vượt quá 50% giá trị đơn hàng (dù voucher ghi giảm nhiều hơn)

Viết 12 test case bao gồm bắt buộc: dùng lại voucher đã dùng, voucher hết hạn đúng
ngày (boundary), đơn hàng dưới ngưỡng tối thiểu, cố áp 2 voucher cùng lúc, và
trường hợp giảm giá tính ra vượt 50% (kiểm tra có bị cap đúng không).

Định dạng: bảng Given-When-Then, có cột Priority.

Business rule là "nguyên liệu" quan trọng nhất — không có nó, AI chỉ có thể đoán các trường hợp thông thường mà bỏ sót chính xác những edge case đặc thù của nghiệp vụ bạn.

Phân Tích Bug

Với phân tích bug, prompt hiệu quả cần evidence cụ thể (log, code, bug report gốc) và yêu cầu AI phân biệt rõ giữa quan sát và suy luận:

Đây là bug report từ user: "Sau khi thanh toán thành công, đơn hàng vẫn hiện
trạng thái Pending trong 5-10 phút mới chuyển sang Paid."

Đây là log liên quan (kèm log thực tế: timestamp các event payment.success,
order.status.update, webhook.received...).

Đây là đoạn code xử lý webhook từ payment gateway (kèm code).

Phân tích:
1. Từ log, xác định khoảng thời gian thực tế giữa payment.success và
   order.status.update (trích timestamp cụ thể)
2. Đối chiếu với code — webhook có được xử lý đồng bộ hay qua queue?
3. Đưa ra giả thuyết nguyên nhân, phân biệt rõ đâu là điều BẠN QUAN SÁT được
   trực tiếp từ log/code, đâu là điều bạn SUY LUẬN (chưa có bằng chứng trực tiếp)
4. Đề xuất log/thông tin bổ sung cần thu thập để xác nhận giả thuyết

Yêu cầu tách "quan sát" và "suy luận" là kỹ thuật quan trọng để tránh AI trình bày một chuỗi suy đoán như thể đó là sự thật đã kiểm chứng — vấn đề thường gặp khi phân tích bug phức tạp có nhiều khả năng.

Lập Kế Hoạch Exploratory Testing

Exploratory testing (kiểm thử thăm dò — không theo test case viết sẵn, mà vừa học vừa thiết kế test song song) cần một loại prompt khác hẳn — không yêu cầu AI viết test case cụ thể, mà yêu cầu AI giúp xây charter (bản định hướng thăm dò) và heuristic (nguyên tắc gợi ý hướng tìm lỗi):

Tôi cần lập charter cho một buổi exploratory testing session (90 phút) cho tính
năng "Giỏ hàng" (Cart) của một app e-commerce mới ra mắt, chưa có nhiều test
coverage tự động.

Hãy:
1. Đề xuất 5 charter (mỗi charter là một câu mục tiêu thăm dò cụ thể, theo mẫu
   "Explore <khu vực> to discover <loại vấn đề>")
2. Với mỗi charter, gợi ý 2-3 heuristic cụ thể nên áp dụng (ví dụ: boundary,
   state transition, interruption/resume)
3. Gợi ý các "biến thể môi trường" nên thử (mạng chậm, đổi thiết bị giữa session,
   nhiều tab cùng lúc) có khả năng gây lỗi cao với tính năng giỏ hàng

Với exploratory testing, AI đóng vai trò tốt nhất là "người gợi ý hướng đi" chứ không phải "người viết sẵn kịch bản" — vì bản chất exploratory testing là con người tự thích ứng theo điều họ quan sát được trong lúc test, AI chỉ giúp mở rộng không gian tìm kiếm ban đầu.

Mẹo: Khi lập charter cho exploratory testing, luôn yêu cầu AI gắn kèm "loại vấn đề nghi ngờ sẽ tìm thấy" cho mỗi charter (ví dụ: "nghi ngờ có race condition khi cập nhật số lượng giỏ hàng từ 2 tab") — điều này biến charter từ một câu mơ hồ thành một giả thuyết có thể kiểm chứng, giúp bạn biết khi nào nên dừng thăm dò một hướng và chuyển sang hướng khác.

Khi Nào Prompt Nên Cụ Thể vs. Mở?

Phổ Độ Cụ Thể

Hãy hình dung một phổ (spectrum) từ hoàn toàn mở đến hoàn toàn cụ thể:

Hoàn toàn mở  ←────────────────────────────────────→  Hoàn toàn cụ thể
"Nghĩ giúp tôi     "Test case nào nên      "Viết đúng 5 test case boundary
về tính năng này"   ưu tiên cho feature X"   cho ngưỡng giá trị 10,000đ,
                                              format bảng, cột: ID|Input|Expected"

Không có điểm nào trên phổ này là "đúng tuyệt đối" — lựa chọn phụ thuộc vào việc bạn đang ở giai đoạn nào của công việc: khám phá vấn đề hay thực thi giải pháp đã rõ.

Khi Nào Prompt Mở Thắng

Prompt mở-ended phù hợp khi:
- Bạn chưa biết chính xác mình cần gì — đang trong giai đoạn khám phá vấn đề (ví dụ mới nhận một feature phức tạp, chưa hình dung hết các rủi ro).
- Bạn muốn AI đưa ra góc nhìn mà bạn CHƯA nghĩ tới — nếu bạn đã quá cụ thể, bạn vô tình giới hạn AI chỉ lặp lại đúng khung bạn đã có sẵn trong đầu, mất đi giá trị "brainstorm".
- Task có bản chất sáng tạo/khám phá (như lập charter exploratory testing ở trên, hoặc brainstorm rủi ro cho một tính năng mới).

Ví dụ prompt mở hiệu quả: "Tính năng chuyển tiền quốc tế này có những rủi ro gì mà một QA engineer nên lo ngại, xét từ góc độ compliance, tài chính, và trải nghiệm người dùng?" — câu hỏi mở nhưng vẫn có khung (3 góc độ) để AI không lan man vô tận.

Khi Nào Prompt Cụ Thể Thắng

Prompt cụ thể phù hợp khi:
- Bạn đã biết rõ mình cần gì, chỉ cần AI thực thi nhanh (ví dụ đã biết chính xác 3 edge case cần test, chỉ cần AI viết ra đúng định dạng).
- Task có độ rủi ro cao, cần độ chính xác, không có chỗ cho "sáng tạo thêm" (viết SQL migration script test, viết test case cho tính năng liên quan đến tiền/dữ liệu nhạy cảm).
- Bạn đã từng bị AI "lan man" sai hướng ở task tương tự trước đó — cụ thể hóa là cách khắc phục trực tiếp.

Phương Pháp Hai Giai Đoạn

Kỹ thuật thực tế hiệu quả nhất khi không chắc nên mở hay cụ thể: chia làm hai lượt hỏi. Lượt 1 dùng prompt mở để khám phá không gian vấn đề, lượt 2 dùng prompt cụ thể (dựa trên kết quả lượt 1) để thực thi:

[Lượt 1 - mở]
"Với tính năng đăng ký tài khoản bằng số điện thoại + OTP, những nhóm rủi ro
nào một QA engineer nên quan tâm? Chỉ cần liệt kê nhóm rủi ro, không cần viết
test case cụ thể."

→ AI trả về ví dụ: rate limiting OTP, số điện thoại đã tồn tại, SIM swap/số điện
thoại bị đổi chủ, quốc gia có định dạng số khác nhau, gửi OTP thất bại do nhà
mạng...

[Lượt 2 - cụ thể, dựa trên kết quả lượt 1]
"Viết 3 test case cụ thể cho nhóm rủi ro 'rate limiting OTP' vừa liệt kê, format
bảng Given-When-Then."

Phương pháp này tận dụng được cả hai thế mạnh: mở để không bỏ sót góc nhìn, cụ thể để có output dùng được ngay — mà không phải đoán trước toàn bộ phạm vi vấn đề ngay từ đầu.

Cân Chỉnh Độ Cụ Thể Trong Thực Tế

Vài dấu hiệu thực tế để tự điều chỉnh:
- Nếu bạn nhận lại output "đúng nhưng thiếu" (thiếu vài trường hợp bạn biết rõ) → cụ thể hóa thêm bằng cách liệt kê rõ những gì PHẢI có.
- Nếu bạn nhận lại output "an toàn nhưng nhạt" (chỉ toàn happy path, không có gì bất ngờ) → mở rộng prompt, bỏ bớt ràng buộc, hỏi thêm "còn góc nhìn nào khác mà tôi chưa đề cập?"
- Nếu output quá dài, lan man, khó dùng ngay → cụ thể hóa Format và Constraint.

Mẹo: Khi mở một task mới hoàn toàn với AI, luôn bắt đầu bằng một câu hỏi mở về rủi ro/góc nhìn trước khi yêu cầu AI sinh ra bất kỳ deliverable cụ thể nào (test case, bug report...). Chi phí của một câu hỏi mở thêm là rất nhỏ (vài chục giây), nhưng lợi ích tránh được việc bỏ sót cả một nhóm rủi ro lớn hơn nhiều lần chi phí đó.

Làm Sao Chẩn Đoán Output AI Kém và Cải Thiện Prompt?

Năm Nhóm Output Kém

Khi output không như mong đợi, việc đầu tiên là phân loại đúng nó thuộc nhóm nào — mỗi nhóm có cách sửa khác nhau:

  1. Quá chung (generic): output đúng về mặt kỹ thuật nhưng không đặc thù cho bối cảnh của bạn, đọc như thể áp dụng cho bất kỳ hệ thống nào. → Nguyên nhân thường là thiếu Context cụ thể.
  2. Sai phạm vi (scope creep/miss): AI trả về nhiều hơn hoặc ít hơn/khác với điều bạn cần (viết cả UI test khi chỉ hỏi API, hoặc bỏ sót một loại test case quan trọng). → Nguyên nhân thường là thiếu Constraint.
  3. Sai định dạng (format mismatch): nội dung đúng nhưng trình bày không theo cách bạn cần (văn xuôi thay vì bảng, thiếu cột cần thiết). → Nguyên nhân thường là thiếu Expected output rõ ràng.
  4. Bịa đặt (hallucination): AI đưa ra thông tin không có trong context bạn cung cấp, hoặc suy diễn sai từ log/code. → Nguyên nhân thường là context không đủ, hoặc AI bị buộc phải "lấp khoảng trống" vì thiếu dữ kiện thật.
  5. Quá nông (shallow): output đúng hướng nhưng thiếu độ sâu, thiếu edge case, chỉ dừng ở mức cơ bản. → Nguyên nhân thường là thiếu role framing đủ mạnh, hoặc thiếu yêu cầu step-by-step reasoning.

Checklist Debug Prompt

Khi gặp output kém, chạy qua checklist này theo thứ tự:

  1. Prompt có đủ 4 thành phần Task/Context/Constraint/Expected output chưa?
  2. Context cung cấp có đủ cụ thể (business rule, dữ liệu thật) hay còn mô tả chung chung?
  3. Có ràng buộc rõ về những gì KHÔNG muốn AI làm chưa (loại trừ phạm vi)?
  4. Có ví dụ mẫu (few-shot) cho định dạng mong muốn chưa?
  5. Role frame đã đủ "sắc" để kéo output lên đúng mức chuyên môn cần chưa?
  6. Nếu task cần lập luận phức tạp, đã yêu cầu step-by-step chưa?

Vòng Lặp Tinh Chỉnh Lặp Đi Lặp Lại

Viết prompt hiệu quả hiếm khi đúng ngay từ lần đầu với các task phức tạp — nó là một vòng lặp tinh chỉnh (iterative refinement): gửi prompt → nhận output → chẩn đoán loại lỗi (theo 5 nhóm trên) → sửa đúng phần bị thiếu → gửi lại. Điểm quan trọng: đừng viết lại toàn bộ prompt từ đầu mỗi lần — chỉ sửa đúng phần đã xác định là nguyên nhân, giữ nguyên phần đang hoạt động tốt. Điều này giúp bạn học được dần dần "công thức" prompt nào hiệu quả cho loại task nào, tích lũy thành thư viện prompt cá nhân theo thời gian.

Cũng nên tận dụng ngay chính AI để debug prompt của bạn: "Tôi vừa hỏi bạn X, và bạn trả lời Y — nhưng tôi cần Z. Theo bạn, phần nào trong prompt của tôi khiến bạn hiểu chưa đúng ý?" — nhiều khi AI có thể tự chỉ ra chính xác điểm mơ hồ trong prompt của bạn.

Dùng "Hỏi Trước Khi Sinh" Cho Các Prompt Rủi Ro Cao

Với các task quan trọng — nơi một output sai có thể gây hậu quả lớn (ví dụ viết test plan cho migration dữ liệu production, phân tích bug ảnh hưởng đến tiền của khách hàng) — kỹ thuật "ask before you generate" (hỏi trước khi sinh) rất hữu ích: yêu cầu AI hỏi lại các câu cần làm rõ TRƯỚC KHI sinh ra deliverable, thay vì để nó tự giả định và sinh ngay:

Tôi cần viết test plan cho việc migrate dữ liệu user từ hệ thống cũ sang hệ thống
mới. TRƯỚC KHI bạn viết test plan, hãy hỏi tôi tất cả câu hỏi cần làm rõ mà bạn
thấy quan trọng (ví dụ về khối lượng dữ liệu, downtime cho phép, rollback plan...).
Đừng viết test plan ngay, chỉ hỏi trước.

Kỹ thuật này đảo ngược trình tự thông thường (bạn hỏi → AI trả lời) thành (AI hỏi → bạn trả lời → AI mới sinh output), giúp lấp đầy chính những khoảng trống Context mà bạn không nhận ra mình đang thiếu — đặc biệt hữu ích khi bạn tự biết mình chưa nắm hết mọi chi tiết cần thiết của task.

Mẹo: Lưu lại các cặp "prompt gốc → output kém → prompt đã sửa → output tốt" cho các task quan trọng đã từng gặp vấn đề. Đây chính là dữ liệu quý nhất để xây thư viện prompt template của riêng bạn — thứ giá trị hơn nhiều so với việc nhớ lý thuyết chung, vì nó phản ánh chính xác những "điểm mù" thường lặp lại trong domain nghiệp vụ mà bạn đang làm.