TDD — Giới thiệu và Nguyên lý
"Clean code that works — in 30-minute cycles." — Kent Beck, "Test-Driven Development: By Example", 2002
Test-Driven Development (TDD) là một kỹ thuật phát triển phần mềm trong đó bạn viết test trước khi viết code production. Không phải "test sau khi code" — mà là test dẫn dắt thiết kế. Kent Beck, người đã "tái khám phá" và hệ thống hóa TDD vào đầu những năm 2000, mô tả nó như một kỹ thuật để đạt được "code sạch mà chạy được" thông qua các chu kỳ ngắn lặp đi lặp lại. TDD không chỉ là về testing — nó là về thiết kế phần mềm. Test trong TDD không phải mục đích cuối cùng, mà là công cụ để đạt được thiết kế tốt hơn, code an toàn hơn, và quy trình làm việc hiệu quả hơn.
Lịch sử của TDD
TDD không ra đời trong chân không. Nó là kết quả của nhiều thập kỷ tiến hóa trong tư duy về chất lượng phần mềm:
| Thời kỳ | Sự kiện | Tác động |
|---|---|---|
| 1968 | NATO Software Engineering Conference | Lần đầu tiên "software crisis" được thừa nhận — phần mềm quá phức tạp, lỗi quá nhiều |
| 1970s | Dijkstra và kiểm chứng hình thức | Ý tưởng viết specification trước code, dùng toán học để chứng minh tính đúng đắn |
| 1980s | Extreme Programming (XP) khởi nguồn | Kent Beck làm việc với Ward Cunningham, giới thiệu khái niệm "test-first" trong dự án Chrysler C3 |
| 1999 | Extreme Programming Explained — Kent Beck | Test-first là một trong 12 practice cốt lõi của XP |
| 2002 | Test-Driven Development: By Example — Kent Beck | TDD chính thức được định nghĩa như một kỹ thuật độc lập |
| 2003 | JUnit ra đời (Beck & Gamma) | Framework testing cho Java, tạo nền tảng cho xUnit family |
| 2005 | pyTest ra đời | Python testing framework, dần trở thành tiêu chuẩn cho Python TDD |
| 2006 | Nghiên cứu của Microsoft Research | Bằng chứng thực nghiệm đầu tiên về hiệu quả của TDD trong công nghiệp |
| 2010s | TDD được áp dụng rộng rãi | Google, Microsoft, Amazon áp dụng TDD ở quy mô lớn |
| 2020s | TDD trong kỷ nguyên AI | TDD vẫn là best practice — AI hỗ trợ viết test nhưng TDD cycle vẫn do developer kiểm soát |
Kent Beck thường kể câu chuyện về dự án Chrysler Comprehensive Compensation (C3) năm 1996 — dự án payroll system đầu tiên áp dụng XP và test-first. Ông nhận thấy rằng viết test trước không chỉ giúp giảm bug, mà còn thay đổi cách thiết kế code. Khi bạn viết test trước, bạn buộc phải suy nghĩ về interface từ góc nhìn của người dùng (client code), dẫn đến thiết kế đơn giản và trực quan hơn.
Red-Green-Refactor: Vòng đời cơ bản của TDD
TDD xoay quanh một chu kỳ 3 bước cực kỳ đơn giản nhưng sâu sắc:
🔴 Red: Viết một test bị fail
Trước khi viết bất kỳ code production nào, bạn viết một test kiểm tra hành vi mong đợi. Test này phải fail (đèn đỏ) vì code chưa tồn tại.
# test_calculator.py — Bước RED
from calculator import Calculator
def test_add_returns_sum_of_two_numbers():
calc = Calculator()
assert calc.add(2, 3) == 5
Khi chạy test này (chưa có class Calculator), pytest báo lỗi ModuleNotFoundError hoặc AttributeError:
$ pytest test_calculator.py -v
============================= test session starts =============================
collected 0 items / 1 error
=================================== ERRORS ====================================
_________________ ERROR collecting test_calculator.py __________________
ImportError while importing 'test_calculator': No module named 'calculator'
=========================== 1 error in 0.12s ============================
Đây là RED — test fail đúng như kỳ vọng.