·

Tiếng Việt: Providing the right QA context

Providing the right QA context

Một trong những sai lầm phổ biến nhất khi làm việc với AI trong QA không phải là viết prompt dở — mà là đưa sai loại context, hoặc đưa đúng loại nhưng quá nhiều/quá ít. Bạn có thể có prompt architecture hoàn hảo (đã học ở các bài trước), nhưng nếu context đưa vào là một mớ hỗn độn requirement, code, và log lẫn lộn không có chọn lọc, AI vẫn sẽ cho ra kết quả tệ. Bài này tập trung vào kỹ năng cốt lõi: chọn đúng context, đúng lượng, đúng cách trình bày, cho từng loại task QA.

Nên Đưa Context Nào Cho Test Planning vs. Test Generation vs. Bug Analysis?

Ba Hồ Sơ Context (Context Profile)

Ba loại task QA phổ biến nhất cần ba "hồ sơ context" khác nhau — nhầm lẫn giữa chúng là nguyên nhân chính gây lãng phí token và kết quả lệch hướng:

Test Planning (lập kế hoạch test) cần context ở tầm rộng, ít chi tiết kỹ thuật: requirement/user story ở mức tính năng, sơ đồ luồng nghiệp vụ (business flow), danh sách các module/hệ thống liên quan, và mức độ rủi ro tổng thể của dự án (fintech khác e-commerce khác nội bộ). KHÔNG cần code chi tiết ở giai đoạn này — code chi tiết chỉ gây nhiễu khi mục tiêu là xác định phạm vi test, chưa phải nội dung test case.

Test Generation (sinh test case) cần context ở tầm hẹp, chi tiết kỹ thuật cao: business rule cụ thể, API spec/schema chính xác, giá trị boundary cụ thể (ngưỡng số tiền, độ dài chuỗi, thời gian hết hạn), và test case cũ để tham chiếu style. Ở giai đoạn này, context mơ hồ ở tầm rộng (như "tính năng thanh toán quan trọng") không giúp được gì — AI cần số liệu, quy tắc, schema cụ thể để sinh ra test case có giá trị thật.

Bug Analysis (phân tích bug) cần context là evidence (bằng chứng thực tế): log, stack trace, code liên quan trực tiếp đến lỗi, bug report gốc từ người dùng/tester, và lịch sử thay đổi gần đây (git log/changelog) nếu là regression. Ở đây, requirement/user story ít quan trọng hơn — điều cần là dữ liệu về CHUYỆN ĐÃ XẢY RA, không phải chuyện LẼ RA phải xảy ra.

Các Lỗi Trộn Context Thường Gặp

  • Đưa code chi tiết vào test planning: khiến AI "chìm" vào chi tiết implementation, quên mất câu hỏi thật là "phạm vi test nên rộng đến đâu" — dễ nhận được một bản outline test plan lẫn lộn với review code.
  • Đưa requirement mơ hồ vào test generation: khiến AI phải tự bịa ra business rule để lấp khoảng trống, sinh ra test case "nghe hợp lý" nhưng không khớp với quy tắc thật của hệ thống — nguy hiểm vì output trông rất chuyên nghiệp, dễ bị tin dùng nhầm.
  • Đưa yêu cầu nghiệp vụ (business requirement) thay vì evidence vào bug analysis: dẫn đến AI phân tích "lẽ ra hệ thống nên làm gì" thay vì "hệ thống đang thực sự làm gì và tại sao" — hai câu hỏi khác nhau hoàn toàn khi debug.
  • Trộn context của nhiều task cũ trong cùng một session dài: khi bạn chuyển từ test planning sang bug analysis trong cùng cuộc hội thoại mà không "dọn" context cũ, AI có xu hướng vô tình mang các giả định từ task trước lẫn vào task sau.

Mẹo: Trước khi gõ prompt, tự hỏi một câu duy nhất: "Tôi đang ở giai đoạn PHẠM VI (planning), NỘI DUNG (generation), hay NGUYÊN NHÂN (analysis)?" Câu trả lời quyết định ngay loại context nào cần ưu tiên đưa vào — đây là bước phân loại nhanh nhất, tiết kiệm nhiều thời gian hơn việc cố nhớ một checklist dài.

Làm Sao Đưa Requirement và User Story Vào Làm Context AI Hiệu Quả?

Điều Gì Khiến Requirement Trở Thành Context Tốt

Requirement thô (raw) — kiểu viết chung chung, thiếu tiêu chí nghiệm thu rõ ràng — là loại context yếu nhất bạn có thể đưa cho AI, vì nó buộc AI phải "đoán" ý định nghiệp vụ. Requirement tốt làm context AI cần có:
- Acceptance Criteria (AC — tiêu chí nghiệm thu) rõ ràng, tốt nhất ở dạng Given-When-Then hoặc danh sách điều kiện cụ thể.
- Giá trị số cụ thể thay vì mô tả định tính: "hiệu lực OTP 5 phút" thay vì "OTP có thời hạn ngắn".
- Điều kiện biên (edge condition) đã được nêu rõ trong requirement, không chỉ happy path.
- Ngữ cảnh nghiệp vụ — vì sao tính năng này tồn tại, ai dùng nó, hậu quả nếu sai (giúp AI hiểu mức độ nghiêm trọng cần cân nhắc khi thiết kế test).

Định Dạng Requirement Cho Context AI

Khi requirement gốc (trong Jira, Confluence...) viết dài dòng, lộn xộn, đừng dán nguyên văn — hãy chuẩn hóa lại thành cấu trúc gọn trước khi đưa vào prompt:

User Story: Là một user, tôi muốn đặt lại mật khẩu qua email khi quên, để tôi
có thể truy cập lại tài khoản.

Acceptance Criteria:
- AC1: Given user nhập email đã đăng ký, When submit form quên mật khẩu,
  Then hệ thống gửi email chứa link reset (hiệu lực 30 phút)
- AC2: Given user click link đã hết hạn, When truy cập trang reset,
  Then hệ thống hiển thị thông báo "Link đã hết hạn" và không cho đổi password
- AC3: Given user nhập email chưa đăng ký, When submit form,
  Then hệ thống hiển thị thông báo chung (không tiết lộ email có tồn tại hay không,
  để tránh account enumeration)

Định dạng Given-When-Then không chỉ dễ đọc với người — nó cũng là cấu trúc AI "hiểu" tốt nhất vì nó ánh xạ trực tiếp sang cấu trúc test case, giảm khoảng cách suy luận cần thiết giữa requirement và test case sinh ra.

Trích AC Từ User Story Cho Context AI

Nhiều requirement thực tế trong công việc không có AC viết sẵn rõ ràng — chỉ là một đoạn mô tả tính năng. Trong trường hợp này, một kỹ thuật hữu ích là dùng AI để tự trích AC trước, rồi mới dùng AC đó làm context cho bước sinh test case:

Đây là mô tả tính năng (dán mô tả thô, dài, thiếu cấu trúc).

Hãy trích ra Acceptance Criteria dạng Given-When-Then từ mô tả trên. Nếu có
điều kiện biên hoặc trường hợp lỗi được ngụ ý nhưng không nói rõ, hãy đánh dấu
là "[NGỤ Ý - CẦN XÁC NHẬN]" thay vì tự khẳng định chắc chắn.

Bước trung gian này rất quan trọng — nó tách rõ "AI đang diễn giải" khỏi "AI đang khẳng định sự thật", giúp bạn biết chỗ nào cần quay lại hỏi Business Analyst/Product Owner để xác nhận trước khi tiếp tục sinh test case dựa trên một giả định sai.

Xử Lý Requirement Mơ Hồ hoặc Thiếu

Khi requirement không đầy đủ (tình huống rất thường gặp trong thực tế), đừng để AI tự lấp khoảng trống một cách âm thầm. Yêu cầu rõ:

Requirement dưới đây thiếu chi tiết về hành vi khi mạng bị mất giữa lúc thanh
toán. Khi viết test case, với những phần requirement không rõ, hãy liệt kê
riêng thành mục "Giả định cần xác nhận với Product Owner" thay vì tự quyết định
hành vi mong đợi.

Kỹ thuật này biến một điểm yếu (requirement thiếu) thành một sản phẩm phụ hữu ích (danh sách câu hỏi cần hỏi PO/BA) — thường có giá trị hơn cả bộ test case, vì nó giúp phát hiện lỗ hổng trong requirement trước khi code được viết ra.

Mẹo: Khi nhận một requirement mới, luôn chạy nó qua AI với câu hỏi "Requirement này còn thiếu thông tin gì để có thể viết test case đầy đủ?" TRƯỚC KHI yêu cầu AI viết test case thật. Việc này thường lộ ra 3-5 câu hỏi quan trọng bạn nên hỏi PO/BA ngay từ đầu sprint, thay vì phát hiện ra giữa lúc test.

Làm Sao Dùng Code Snippet Làm Context Mà Không Làm Model Bị Quá Tải?

Chọn Đúng Đoạn Code Cần Đưa Vào

Nguyên tắc vàng: chỉ đưa code trực tiếp liên quan đến hành vi cần test/debug, không đưa cả file hoặc cả module "cho chắc". Thứ tự ưu tiên khi chọn code:
1. Hàm/method xử lý trực tiếp logic đang quan tâm.
2. Định nghĩa type/interface/schema của dữ liệu đầu vào-đầu ra liên quan.
3. Validation logic hoặc business rule được code hóa (constants, config giới hạn).
4. Chỉ khi thực sự cần: code của các hàm được gọi bên trong (dependency), và chỉ 1 cấp sâu, không truy sâu vô hạn.

Với các hệ thống lớn, code có thể có call chain (chuỗi gọi hàm) sâu 5-6 tầng — không cần và không nên đưa hết cả chuỗi vào context, chỉ cần tầng liên quan trực tiếp cộng với một câu mô tả ngắn về hành vi của các tầng sâu hơn nếu cần thiết.

Best Practice Khi Đưa Code Snippet

  • Luôn giữ nguyên comment và docstring trong đoạn code — chúng thường chứa business rule ngầm ("// max 3 lần retry theo quy định compliance") mà nếu bị cắt, AI mất luôn manh mối quan trọng.
  • Ghi rõ đường dẫn file và ngữ cảnh trước mỗi đoạn code: "Đây là hàm validateOrderTotal trong file src/services/orderValidation.js, được gọi từ endpoint POST /api/orders trước khi lưu DB."
  • Loại bỏ code không liên quan trong cùng file (như các hàm khác trong file không liên quan đến câu hỏi) — dán cả file 800 dòng để hỏi về 1 hàm 20 dòng là lãng phí và gây nhiễu.
  • Giữ format code nguyên bản (không paste qua công cụ làm mất indentation) — với Python đặc biệt quan trọng vì indentation là cú pháp.

Đưa Code Theo Từng Phạm Vi Test Khác Nhau

Lượng và loại code cần đưa thay đổi theo phạm vi (scope) của test đang làm:

  • Unit test: chỉ cần đúng hàm/class đang test, cộng interface của các dependency nó gọi (không cần implementation đầy đủ của dependency, chỉ cần signature).
  • Integration test: cần thêm code ở lớp kết nối giữa các thành phần (ví dụ code gọi API, code xử lý response, mapping dữ liệu giữa hai service).
  • End-to-end test: thường KHÔNG cần code chi tiết — cần luồng nghiệp vụ (business flow) và selector/element ID của UI, vì E2E test quan tâm đến hành vi quan sát được từ ngoài, không phải implementation nội bộ.
  • API contract test: cần chính xác schema/spec (OpenAPI, GraphQL schema, protobuf definition) — không cần code implementation, vì contract test kiểm tra tuân thủ hợp đồng interface, không kiểm tra logic bên trong.

Mẹo: Trước khi copy-paste một đoạn code dài vào prompt, tự hỏi "Nếu tôi xóa dòng này, câu trả lời của AI có thay đổi không?" Với mọi dòng mà câu trả lời là "không", hãy xóa nó khỏi context — nguyên tắc đơn giản này thường giảm được 30-50% lượng code không cần thiết trong một context vốn đã căng.

Làm Sao Dùng Test Case Cũ Để Hướng Dẫn AI Sinh Test Case Mới?

Vì Sao Context Tham Chiếu Style Quan Trọng

Nếu bạn chỉ đưa requirement mà không đưa test case cũ làm mẫu, AI sẽ sinh test case theo "style mặc định" của nó — thường khác với convention team đang dùng (đặt tên khác, cấu trúc khác, mức độ chi tiết khác). Kết quả là bạn phải tốn công sửa định dạng thủ công dù nội dung logic đúng. Đưa 1-2 test case cũ làm ví dụ mẫu (few-shot) là cách rẻ nhất và hiệu quả nhất để loại bỏ hoàn toàn vấn đề này — AI học theo pattern cụ thể từ ví dụ tốt hơn nhiều so với việc bạn mô tả style bằng lời.

Chọn Đúng File Test Mẫu

Không phải test case cũ nào cũng nên dùng làm mẫu. Tiêu chí chọn:
- Chọn file đã được review và merge, không phải bản draft hoặc bản đang gây tranh cãi về style.
- Chọn file cùng loại với test cần sinh (đừng dùng unit test làm mẫu để sinh E2E test).
- Chọn file gần đây nhất theo convention hiện tại của team — nếu team vừa đổi convention 2 tháng trước, dùng file cũ hơn làm mẫu sẽ khiến AI học theo style đã lỗi thời.
- Ưu tiên file có độ phức tạp tương đương với task hiện tại — dùng một file test rất đơn giản làm mẫu cho một tính năng phức tạp nhiều edge case sẽ khiến AI đánh giá thấp mức độ chi tiết cần có.

Cách Đóng Khung Ví Dụ Trong Prompt

Khi đưa test case cũ vào prompt, luôn nói rõ AI nên học gì từ ví dụ đó — style, cấu trúc, mức độ chi tiết — không phải học nội dung nghiệp vụ của ví dụ:

Đây là ví dụ test case đã có, viết cho tính năng khác (đăng nhập bằng password),
dùng làm MẪU VỀ STYLE (không phải nội dung):

[dán test case mẫu]

Hãy viết test case cho tính năng đăng ký bằng số điện thoại theo ĐÚNG cấu trúc,
mức độ chi tiết, và cách đặt tên như ví dụ trên — nhưng nội dung nghiệp vụ áp
dụng cho tính năng đăng ký, không phải đăng nhập.

Câu "làm MẪU VỀ STYLE (không phải nội dung)" là chi tiết nhỏ nhưng quan trọng — thiếu câu này, một số model có xu hướng vô tình trộn lẫn nội dung của ví dụ vào test case mới (ví dụ nhắc nhầm đến "password" khi đang viết test cho đăng ký bằng OTP).

Dùng Test Case Cũ Để Xác Định Lỗ Hổng Coverage

Ngoài việc học style, test case cũ còn có giá trị lớn trong việc AI hỗ trợ tìm lỗ hổng coverage (coverage gap) — so sánh test đã có với business rule/requirement để tìm ra phần chưa được cover:

Đây là toàn bộ danh sách tên test case hiện có cho module giỏ hàng (dán danh sách
tên, không cần nội dung đầy đủ — dùng lệnh grep đã học ở bài trước để lấy danh
sách này).

Đây là business rule đầy đủ của module giỏ hàng (dán business rule).

So sánh danh sách test hiện có với business rule, chỉ ra những rule nào CHƯA có
test case nào cover (dựa trên tên test — nếu không chắc, đánh dấu "CẦN KIỂM TRA
THỦ CÔNG" thay vì khẳng định chắc)

Đây là một trong những use case AI mang lại giá trị cao nhất cho QA — vì việc rà soát coverage gap thủ công trên một suite có hàng trăm test case là công việc tốn thời gian và dễ bỏ sót do mỏi mắt, còn AI có thể quét nhanh và có hệ thống hơn (dù vẫn cần con người xác nhận lại các kết luận "CẦN KIỂM TRA THỦ CÔNG").

Xây Dựng Test Archive Làm Context Cho AI

Với các team làm việc thường xuyên với AI để sinh test case, nên đầu tư xây một test archive nhỏ — một thư mục tổng hợp các test case "mẫu chuẩn" (gold standard) đại diện cho từng loại tình huống phổ biến (test API CRUD cơ bản, test validation, test authorization, test business rule phức tạp). Archive này không cần lớn — 5-10 file mẫu chất lượng cao, được duy trì cẩn thận, có giá trị hơn nhiều so với việc mỗi lần cần ví dụ lại tìm ngẫu nhiên một file bất kỳ trong codebase.

Ngăn Style Trôi Dạt Theo Thời Gian

Một vấn đề âm thầm khi dùng AI sinh test case liên tục qua nhiều tháng: style drift (trôi dạt phong cách) — mỗi lần AI sinh test case mới dựa trên ví dụ cũ, có một chút sai lệch nhỏ tích lũy dần (đặt tên hơi khác, cấu trúc hơi khác), và sau vài chục lần, style của test suite dần không còn nhất quán. Cách ngăn:
- Định kỳ cập nhật test archive với các ví dụ mới nhất, đã được review, thay vì để archive "đóng băng" từ ngày đầu.
- Review style trong code review, không chỉ review logic — coi lệch style của test sinh bởi AI là một loại vấn đề cần fix, không phải chi tiết nhỏ có thể bỏ qua.
- Định kỳ (mỗi quý) làm sạch archive: loại bỏ ví dụ đã lỗi thời, thêm ví dụ mới phản ánh convention hiện tại.

Mẹo: Đừng dùng test case đầu tiên bạn tìm được trong codebase làm mẫu — dành 5 phút chọn một file test THỰC SỰ chất lượng cao (đã được review kỹ, không có code smell, đặt tên rõ ràng) để làm ví dụ few-shot. Chất lượng của ví dụ mẫu ảnh hưởng trực tiếp và mạnh hơn bất kỳ instruction bằng lời nào đến chất lượng test case AI sinh ra sau đó.