AllianceProject Handbook
← Knowledge

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.

Cập nhật 12/09/2026testdevshift left

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ó testKhô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ệuCấu hình tĩnh
Máy trạng thái và điều kiện chuyển trạng tháiGiao diện thuần trình bày, không nhánh
Kiểm tra phân quyềnThư 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ự:

  1. Viết test tái hiện bug — nó phải đỏ.
  2. Sửa code.
  3. 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 expect gì 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ý:

  1. Phát hiện chập chờn → mở issue ngay, gán cho chủ sở hữu phần đó.
  2. Sửa trong 24 giờ, hoặc tắt test đó kèm issue theo dõi.
  3. 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:

  1. 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.
  2. 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.