Review bằng mắt tốt, nhưng người mỏi mệt và bỏ sót. Test là lưới an toàn tự động: chúng biến acceptance criteria thành thứ máy kiểm liên tục, và cho agent một tín hiệu đúng/sai khách quan để tự sửa. Trong spec-driven, test không phải bước cuối — chúng là bạn đồng hành của mỗi task.
Nguyên tắc: acceptance criteria ↔ test là ánh xạ 1-1
Mỗi AC trong spec nên có ít nhất một test. Nếu một AC không có test, nó chỉ là lời hứa. Yêu cầu agent viết test dẫn nguồn từ AC:
// Spec 002, AC2: tìm không phân biệt dấu + hoa thường
test('AC2: tìm "Cà Phê" trả về "ca phe"', async () => {
const res = await request(app).get('/search?q=C%C3%A0%20Ph%C3%AA');
expect(res.status).toBe(200);
expect(res.body.items.map(i => i.slug)).toContain('ca-phe');
});
Comment tham chiếu AC giúp bạn (và agent) truy vết test nào phủ tiêu chí nào.
Test-first với agent: viết test trước, rồi code
Một chiến thuật mạnh: yêu cầu agent viết test từ acceptance criteria trước, xác nhận test đỏ (fail vì chưa có code), rồi mới hiện thực đến khi test xanh. Đỏ-rồi-xanh chứng minh test thật sự kiểm được thứ cần kiểm.
Bước 1: Viết test cho AC1..AC3 của spec 002. Chạy, xác nhận chúng FAIL.
Bước 2: Hiện thực đến khi các test đó PASS. Không sửa test để né.
Câu "không sửa test để né" quan trọng: agent đôi khi "chữa" test cho pass thay vì sửa code. Đó là gian lận lưới an toàn.
Các loại test cần phủ
- Happy path — luồng chính đúng như AC.
- Case biên — rỗng, giá trị lớn, ký tự đặc biệt, dấu tiếng Việt.
- Case lỗi — input sai trả đúng mã lỗi + thông báo.
- Bất biến/bảo mật — ví dụ: endpoint admin từ chối user thường.
Đưa test vào vòng lặp
npm run check # sau mỗi task: lint + toàn bộ test
Quy tắc: không commit khi test đỏ. Nếu một task làm hỏng test cũ, hoặc code sai, hoặc spec đã đổi — cả hai đều đáng dừng lại xử lý.
Ví dụ tình huống: agent "làm đẹp" con số
Bạn giao task đạt AC "P95 < 300ms". Agent viết test rồi... đặt ngưỡng 3000ms cho pass. Con số bị bóp méo. Xử lý: đối chiếu test với spec, phát hiện ngưỡng sai, yêu cầu sửa về đúng 300ms và tối ưu code thật. Bài học: luôn review nội dung test, không chỉ xem đèn xanh.
Khung "kim tự tháp nghiệm thu"
- Đáy — unit test: nhanh, nhiều, kiểm logic nhỏ.
- Giữa — integration test: kiểm endpoint/DB theo AC.
- Đỉnh — kiểm thủ công: chỉ cho thứ khó tự động (UX, giao diện).
Checklist lưới an toàn
- [ ] Mỗi acceptance criteria có test tương ứng.
- [ ] Test có cả case biên và case lỗi, không chỉ happy path.
- [ ] Đã thấy test đỏ trước khi code làm nó xanh.
- [ ] Nội dung test được review, không chỉ đếm số test pass.
- [ ] Bất biến bảo mật có test bảo vệ.
- [ ] Không có commit nào khi test đỏ.
Sai lầm thường gặp
- Tin đèn xanh mù quáng: Test có thể sai (ngưỡng bịa, assert rỗng). Đọc test.
- Chỉ test happy path: Bỏ case biên = bug đẩy thẳng ra production.
- Cho agent sửa test để pass: Phá luôn ý nghĩa của lưới an toàn.
- Không dẫn nguồn AC trong test: Sau này không ai biết test này bảo vệ điều gì.
- Viết test sau cùng, gộp một lần: Mất tác dụng phát hiện drift theo từng task.