
TDD (Test-Driven Development)
TDD (Test-Driven Development)
Giai đoạn Đỏ
Giai đoạn Đỏ
Giai đoạn Xanh
Giai đoạn Xanh
Giai đoạn Tái cấu trúc
Giai đoạn Tái cấu trúc
Trong một thời gian dài, tôi đã viết các bài kiểm tra theo cách mà hầu hết các nhà phát triển vẫn làm: sau khi viết mã. Tôi sẽ hoàn thành một tính năng, cảm thấy khá hài lòng về nó, sau đó viết các bài kiểm tra để xác nhận nó hoạt động đúng như tôi nghĩ. Các bài kiểm tra luôn vượt qua. Đó là sai lầm đầu tiên của tôi.
Một buổi chiều nọ, tôi tái cấu trúc một hàm tiện ích - dọn dẹp nó, làm cho nó "tốt hơn" - và làm hỏng nó theo một cách mà tôi không nhận ra trong hai ngày. Các bài kiểm tra hiện có đang kiểm tra cách triển khai của tôi, chứ không phải hành vi. Khi tôi thay đổi cách triển khai, các bài kiểm tra cũng thay đổi theo. Không ai phát hiện ra cho đến khi QA.
Đó là lúc tôi thực sự thử TDD. Không phải vì ai đó bảo tôi làm, mà vì tôi đã quá mệt mỏi với kiểu lỗi cụ thể đó.
| Giai đoạn | Hành động | Tư duy | Mục tiêu |
|---|---|---|---|
| 🔴 Đỏ | Viết bài kiểm tra thất bại | Định nghĩa hành vi mong muốn trước | Bài kiểm tra mô tả API |
| 🟢 Xanh | Viết mã tối thiểu để vượt qua | Chống lại việc thiết kế quá mức | Làm cho bài kiểm tra vượt qua - không hơn |
| 🔵 Tái cấu trúc | Cải thiện thiết kế & loại bỏ trùng lặp | Các bài kiểm tra là lưới an toàn của bạn | Mã sạch trong khi vẫn giữ màu xanh |
TDD tuân theo một nhịp điệu ba bước lặp lại. Một khi bạn đã thực hiện nó vài lần, nó sẽ trở thành phản xạ - nhưng vài lần đầu tiên nó có vẻ ngược đời.
Mục đích của giai đoạn Đỏ trong TDD là gì?
Ví dụ trong sách giáo khoa nhỏ, nhưng việc thực hiện nó từ từ là đáng giá.
Viết bài kiểm tra trước. Nó thất bại - multiply chưa tồn tại. Không sao cả. Đó là mục đích.
test('multiplies two numbers', () => {
expect(multiply(3, 4)).toBe(12);
});
Chỉ viết đủ mã để đáp ứng bài kiểm tra. Không hơn. Không tối ưu hóa sớm.
function multiply(a, b) {
return a * b;
}
Mã đã sạch ở đây. Nhưng khi mọi thứ phát triển, đây là nơi bạn loại bỏ sự trùng lặp, cải thiện cách đặt tên và dọn dẹp các trừu tượng - trong khi các bài kiểm tra xác nhận không có gì bị hỏng.
Đây là cách tái cấu trúc hướng tới sự đúng đắn trông như thế nào khi bạn thêm an toàn kiểu:
function multiply(a, b) {if (typeof a !== 'number' || typeof b !== 'number') {throw new TypeError('Both arguments must be numbers');}return a * b;}
Sau khi làm cho một bài kiểm tra vượt qua (giai đoạn Xanh), bạn nên làm gì tiếp theo?
Tôi đã hoài nghi về những lợi ích thiết kế cho đến khi tôi thử TDD trên một đoạn mã có yêu cầu không rõ ràng. Việc viết bài kiểm tra trước buộc tôi phải hỏi: thứ này thực sự nên làm gì? Tôi phải định nghĩa giao diện trước khi viết bất kỳ logic nào. Hóa ra đó là câu hỏi khó hơn - và quan trọng hơn.
| Không có TDD | Với TDD | |
|---|---|---|
| Phát hiện lỗi | Tìm thấy trong sản xuất hoặc kiểm thử thủ công | Phát hiện ngay lập tức trong quá trình phát triển |
| Thiết kế | Triển khai thúc đẩy thiết kế API | API được thiết kế trước (kiểm thử trước) |
| Tái cấu trúc | Rủi ro - không có lưới an toàn | Tự tin - các bài kiểm tra xác minh hành vi |
| Tài liệu | Tài liệu riêng biệt bị lỗi thời | Các bài kiểm tra = tài liệu luôn cập nhật |
Sai lầm phổ biến nhất khi bắt đầu với TDD là gì?
Bắt đầu nhỏ. Chọn một hàm tiện ích - một bộ định dạng, một bộ xác thực, một cái gì đó khép kín. Viết bài kiểm tra trước, xem nó thất bại, sau đó làm cho nó vượt qua. Một chu trình. Xem cảm giác thế nào.
Những lợi ích thiết kế không xuất hiện trong một hàm ba dòng. Chúng xuất hiện khi bạn đang xây dựng một cái gì đó có độ phức tạp thực sự và các bài kiểm tra của bạn liên tục cho bạn biết API đang gây nhầm lẫn ở đâu hoặc logic có quá nhiều trách nhiệm ở đâu. Đó là TDD đang làm công việc của nó.
TDD Testing JavaScript Best PracticesLàm sạch log AI CLI, tạo biểu thức cron, giải mã JWT và tính quyền chmod offline.

Hướng dẫn thực tế về cách viết các bài kiểm thử đơn vị JavaScript bền vững: mẫu AAA, test fixture, kiểm thử dựa trên thuộc tính với fast-check và mocking biên.
Đọc tiếp
Làm chủ kiểm thử E2E với Playwright vào năm 2026: tự động chờ, cách ly ngữ cảnh trình duyệt, chặn mạng, lưu trữ xác thực và song song hóa CI.
Đọc tiếp
So sánh chuyên sâu MSW và WireMock cho kiểm thử tích hợp microservices, các mẫu chặn mạng, thiết lập container và fault injection.
Đọc tiếp