Yêu cầu với lập trình viên
Chuẩn test của dev
Dev chịu trách nhiệm chính về chất lượng phần mình viết. Bài này nói rõ phải viết test gì, viết thế nào, và tự kiểm tra tay những gì trước khi mở PR.
Nội dung bài
Thuật ngữ trong bài (15)
- empty state · trạng thái rỗng
- acceptance criteria · tiêu chí nghiệm thu
- spike · việc tìm hiểu có giới hạn
- CI · tích hợp liên tục
- hotfix · bản vá nóng
- merge · gộp nhánh
- pull request · yêu cầu gộp mã
- refactor · sửa cấu trúc mã
- bug · lỗi
- coverage · độ phủ test
- emulator · máy giả lập
- test case · ca kiểm thử
- release · bản phát hành
- incident · sự cố
- retry · thử lại
Ai chịu trách nhiệm chất lượng
Người viết code. Không phải tester, không phải chủ kỹ thuật, không phải người review.
Mô hình "dev viết code rồi ném cho tester tìm lỗi" là mô hình đẩy lỗi sang phải — nó làm lỗi được phát hiện muộn hơn, đắt hơn, và tạo ra quan hệ đối đầu giữa hai vai trò. Ở đây, test là một phần của việc viết code, không phải một chặng đứng sau.
Người test chuyên trách (nếu có) làm việc khác: thiết kế kịch bản khó, thử phá hệ thống, kiểm thử khám phá — những thứ dev khó tự làm với code của chính mình.
Biến acceptance criteria thành test case — bắt buộc
Trước khi viết code, đọc acceptance criteria và viết ra danh sách test case. Đây là việc bắt buộc, và là điểm shift left có giá trị cao nhất trong toàn bộ quy trình:
- Viết ra test case buộc bạn hiểu yêu cầu cụ thể tới mức thực thi được.
- Yêu cầu nào không biến thành test case được nghĩa là nó còn mơ hồ — hỏi lại ngay bây giờ, lúc chưa mất gì.
- Danh sách này dán thẳng vào phần "Đã test thế nào" của PR.
Ví dụ với acceptance criteria "người dùng lọc được đơn hàng theo trạng thái":
1. Có đơn khớp trạng thái -> hiện đúng các đơn đó
2. Không có đơn nào khớp -> hiện trạng thái rỗng có hướng dẫn, không phải màn hình trắng
3. Chọn nhiều trạng thái -> hiện hợp của các nhóm
4. Bỏ chọn hết -> quay về danh sách đầy đủ
5. Lỗi mạng khi đang lọc -> giữ kết quả cũ, hiện thông báo thử lại được
6. Đổi bộ lọc liên tục -> chỉ kết quả của lần chọn cuối được hiển thị
7. Bộ lọc còn giữ khi quay lại màn hình từ màn chi tiết
Mục 5 và 6 gần như luôn bị bỏ sót nếu không viết danh sách này ra trước.
Phải viết test tự động cho cái gì
| Bắt buộc có test | Không bắt buộc |
|---|---|
| Logic tính toán, quy tắc nghiệp vụ | Code chỉ gọi xuyên qua, không có logic |
| Chuyển đổi, phân tích, định dạng dữ liệu | Cấu hình tĩnh |
| Máy trạng thái và điều kiện chuyển trạng thái | Giao diện thuần trình bày, không nhánh |
| Kiểm tra phân quyền | Thư viện bên thứ ba |
| Xử lý lỗi và trường hợp biên | |
| Mọi bug đã sửa |
Dòng cuối là luật cứng: mỗi bug được sửa phải kèm một test tái hiện bug đó. Trình tự:
- Viết test tái hiện bug — nó phải đỏ.
- Sửa code.
- Test chuyển xanh.
Không làm đủ ba bước thì không có gì chứng minh bạn đã sửa đúng nguyên nhân, và không có gì ngăn bug đó quay lại sau sáu tháng. Một bug quay lại lần hai là lỗi quy trình, không phải xui rủi.
Viết test thế nào
Cấu trúc
Ba khối rõ ràng, cách nhau một dòng trống:
it('không cho chuyển task sang Done khi còn subtask chưa xong', () => {
// Arrange
const task = makeTask({ subtasks: [done(), pending()] });
// Act
const result = moveToDone(task);
// Assert
expect(result.ok).toBe(false);
expect(result.reason).toBe('SUBTASK_PENDING');
});
Tên test
Tên phải mô tả hành vi và điều kiện, đọc được như một câu tiếng Việt hoặc tiếng Anh đủ nghĩa. Người đọc kết quả CI đỏ phải hiểu ngay cái gì hỏng mà không cần mở code.
Xấu: test1 / testOrder / shouldWork
Tốt: "tính tổng đơn hàng làm tròn tới đơn vị đồng, không dùng float"
Tốt: "từ chối gửi tin nhắn khi nội dung rỗng sau khi bỏ khoảng trắng"
Luật bắt buộc
- Một test khẳng định một hành vi. Test kiểm mười thứ thì khi đỏ không biết thứ nào hỏng.
- Test phải độc lập. Chạy riêng lẻ, chạy đảo thứ tự, chạy song song đều phải ra cùng kết quả.
- Không dùng dữ liệu thật của người dùng. Dựng dữ liệu trong test bằng hàm tạo có tên rõ.
- Không phụ thuộc vào thời gian thật, múi giờ máy, hay mạng thật. Thời gian phải tiêm vào được.
- Test phải có khẳng định thật. Test chạy qua code mà không
expectgì chỉ làm đẹp coverage, không bảo vệ gì cả. - Không test chi tiết cài đặt bên trong. Test hành vi qua giao diện công khai, để refactor không làm vỡ hàng loạt test.
Test chập chờn
Test lúc xanh lúc đỏ mà không đổi code là hỏng, dù nó "thường xanh".
Luật xử lý:
- Phát hiện chập chờn → mở issue ngay, gán cho chủ sở hữu phần đó.
- Sửa trong 24 giờ, hoặc tắt test đó kèm issue theo dõi.
- Không được để nguyên và bảo nhau "chạy lại là xanh".
Lý do nghiêm khắc: một test chập chờn dạy cả đội thói quen bấm chạy lại khi thấy đỏ. Thói quen đó sẽ áp dụng luôn cho lần đỏ thật sự tiếp theo. Một test chập chờn làm hỏng độ tin cậy của toàn bộ bộ test.
Coverage
Đo coverage trên phần code mới thay đổi, không đo trên toàn repo:
- Ngưỡng bắt buộc cho code mới trong PR: 80%.
- Không đặt ngưỡng toàn repo rồi ép cả đội chạy theo con số — nó tạo ra test rác.
- Coverage thấp ở code xử lý tiền, phân quyền, hoặc trạng thái thì bị chặn ở review bất kể con số tổng là bao nhiêu.
Coverage cao không chứng minh code đúng. Coverage thấp ở vùng quan trọng thì chứng minh được là code chưa được bảo vệ. Dùng nó theo chiều đó.
Tự kiểm tra tay trước khi mở PR
Test tự động không thay thế được việc tự mở app lên dùng thử. Danh sách tối thiểu:
- Chạy đúng luồng trong acceptance criteria, từ đầu tới cuối.
- Thử một luồng liền kề có khả năng bị ảnh hưởng.
- Bật chế độ máy bay giữa chừng, rồi bật mạng lại.
- Mạng chậm (dùng công cụ giả lập mạng yếu) — khó chịu hơn mất mạng hẳn.
- Bấm nút gửi/lưu hai lần thật nhanh.
- Xoay ngang màn hình, đổi cỡ chữ hệ thống lên mức lớn nhất.
- Tài khoản không có quyền — có bị chặn đúng không, thông báo có rõ không.
- Dữ liệu rỗng và dữ liệu rất nhiều (cuộn danh sách dài).
- Nâng cấp từ phiên bản trước với dữ liệu cũ trên máy.
- Thử trên thiết bị thật yếu nhất trong danh sách hỗ trợ, không chỉ trên máy giả lập.
Hai mục cuối là hai mục bị bỏ nhiều nhất và sinh ra nhiều sự cố nhất sau release.
Khi nào được phép chưa có test
Chỉ trong hai trường hợp, và cả hai đều phải ghi rõ trong PR:
- Hotfix đang chặn người dùng. Sửa trước, nhưng bắt buộc mở ngay một PR bổ sung test trong 24 giờ. Không có ngoại lệ, không quên.
- Spike thử nghiệm không merge vào
main.
Ngoài hai trường hợp này, "không kịp viết test" không phải lý do. Nó chỉ có nghĩa là hạng mục được ước lượng thiếu — và phần thiếu đó sẽ được trả bằng thời gian sửa bug, với lãi suất.

