Viết unit test đầu tiên: mô hình Arrange - Act - Assert

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Nhiều bạn mới học lập trình thấy test là thứ "dành cho người đi làm" và bỏ qua. Nhưng một unit test đơn giản có thể cứu bạn khỏi hàng giờ debug về sau. Bài này hướng dẫn viết unit test đầu tiên với mô hình AAA dễ nhớ, kèm ví dụ bằng JavaScript (Jest) và Python (pytest).

Unit test là gì?

Unit test là đoạn code nhỏ kiểm tra một đơn vị nhỏ (thường là một hàm) hoạt động đúng. Bạn đưa vào đầu vào cụ thể, chạy hàm, rồi so sánh kết quả với kết quả mong đợi. Test chạy tự động, nhanh, và có thể lặp lại bao nhiêu lần tùy ý.

Lợi ích chính:

  • Phát hiện lỗi sớm khi bạn vừa viết xong.
  • Cho bạn sự tự tin khi sửa hoặc refactor code (test xanh nghĩa là chưa hỏng).
  • Đóng vai trò tài liệu sống: đọc test là hiểu hàm dùng thế nào.

Mô hình AAA

Mỗi test nên chia làm ba phần rõ ràng:

  1. Arrange (Chuẩn bị): thiết lập dữ liệu và điều kiện cần thiết.
  2. Act (Thực hiện): gọi hàm cần kiểm tra.
  3. Assert (Khẳng định): kiểm tra kết quả có đúng như mong đợi.

Cách chia này giúp test dễ đọc, và nếu thấy phần Arrange quá dài, đó là gợi ý code của bạn đang quá phụ thuộc vào nhiều thứ.

Ví dụ với Jest (JavaScript)

Hàm cần test, đặt trong file cart.js:

function calculateTotal(items) {return items.reduce((sum, item) => sum + item.price * item.qty, 0);}module.exports = { calculateTotal };

File test cart.test.js:

const { calculateTotal } = require('./cart');describe('calculateTotal', () => {test('tính đúng tổng tiền nhiều sản phẩm', () => {// Arrangeconst items = [{ price: 10000, qty: 2 },{ price: 5000, qty: 3 },];// Actconst total = calculateTotal(items);// Assertexpect(total).toBe(35000);});test('giỏ hàng rỗng trả về 0', () => {expect(calculateTotal([])).toBe(0);});});

Cài Jest bằng npm install --save-dev jest, thêm "test": "jest" vào phần scripts của package.json, rồi chạy npm test.

Ví dụ với pytest (Python)

# cart.pydef calculate_total(items):return sum(i["price"] * i["qty"] for i in items)# test_cart.pyfrom cart import calculate_totaldef test_calculate_total_nhieu_san_pham():# Arrangeitems = [{"price": 10000, "qty": 2}, {"price": 5000, "qty": 3}]# Acttotal = calculate_total(items)# Assertassert total == 35000def test_gio_hang_rong():assert calculate_total([]) == 0

Cài pytest bằng pip install pytest rồi chạy lệnh pytest trong thư mục dự án.

Nên test những gì?

Với mỗi hàm, hãy nghĩ đến ba nhóm trường hợp:

  • Trường hợp bình thường (happy path): đầu vào hợp lệ, kết quả quen thuộc.
  • Trường hợp biên: rỗng, 0, số âm, giá trị lớn nhất/nhỏ nhất, chuỗi rỗng.
  • Trường hợp lỗi: đầu vào sai, dữ liệu null, hàm ném ngoại lệ đúng như thiết kế.

Đặc điểm của một unit test tốt

  1. Nhanh: chạy trong mili giây để bạn chạy thường xuyên.
  2. Độc lập: không phụ thuộc test khác, thứ tự chạy không quan trọng.
  3. Lặp lại được: cùng kết quả mỗi lần, không phụ thuộc giờ hệ thống hoặc mạng.
  4. Rõ ràng: tên test cho biết đang kiểm tra điều gì và kỳ vọng ra sao.
  5. Kiểm tra một khái niệm: mỗi test một ý, để khi hỏng biết ngay vì sao.

Những sai lầm của người mới

  • Test cách cài đặt bên trong thay vì hành vi, khiến test hỏng mỗi khi refactor.
  • Viết một test khổng lồ kiểm tra mọi thứ cùng lúc.
  • Test phụ thuộc vào database thật hoặc API ngoài (đó là integration test, tốn thời gian hơn).
  • Sao chép logic của hàm vào test để tính kết quả mong đợi, nên test luôn "đúng" kể cả khi hàm sai.
  • Bỏ test khi chúng hỏng thay vì tìm hiểu nguyên nhân.

Kết luận

Bắt đầu thật nhỏ: chọn một hàm thuần trong dự án của bạn, viết ba test cho nó theo mô hình AAA và chạy. Cảm giác thấy dòng chữ màu xanh "passed" sẽ cho bạn động lực để biến việc viết test thành thói quen.

Muốn học kiểm thử cùng các dự án thực hành có hướng dẫn, bạn có thể xem qua các khóa học trên codebem.com.

author_photo
Nguyễn Đình Cường

0 comment