Test Driven Development (TDD) là gì?
1. When to Write Tests? Khi nào thì ta cần viết test? viết test sau quá trình implementation viết test trước quá trình implementation Hiển hiên, 2 ý kiến trên ngược chiều nhau. Bạn sẽ phải chọn một trong 2 cách với từng đoạn code của mình, và dĩ nhiên cả 2 đều được chấp nhận trong quá ...
1. When to Write Tests? Khi nào thì ta cần viết test?
- viết test sau quá trình implementation
- viết test trước quá trình implementation
Hiển hiên, 2 ý kiến trên ngược chiều nhau. Bạn sẽ phải chọn một trong 2 cách với từng đoạn code của mình, và dĩ nhiên cả 2 đều được chấp nhận trong quá trình bạn viết code.
1.1. Test Last
Viết test sau khi code có những mặt ưu và nhược điểm như sau. Ưu điểm chính là test được viết khi những chức năng của object được test đã khá hoàn chỉnh và bạn có sự hiểu biết về nó. Còn nhược điểm chính là nó làm developer tập trung vào test implementation thay vì test interface (behavior). Điều này có thể dẫn tới:
- test dính chặt với code của bạn (tightly coupling) và nó làm bạn phải viết lại test rất nhiều mỗi khi code thay đổi.
- khuyến khích developer được chọn viết test nào trước.
Và lại, khi sử dụng cách tiếp cận "test last", luôn luôn có những sự cám dỗ làm cho developer lười viết test. Tại sao lại phải viết test? Khi bạn nghĩ rằng code của mình chạy khá đúng rồi. Tại sao lại phải viết test? Khi bạn phải viết thứ gì đó rồi chạy nó và làm cho kết quả có màu xanh là được. "test last" yêu cầu ở bạn một tính kỷ luật cực cao trong quá trình viết test sau quá trình implementation. Và khi deadline thúc vào ass, sự cám dỗ bị nổi lên, bạn không viết test - bạn tiết kiệm được rất nhiều thời gian, những unit test không cần thiết. Đối với tôi, đây là những lý do cực kỳ nghiêm trọng để bạn từ bỏ cách tiếp cận "test last". Một trường hợp duy nhất được coi là hợp lý - khi làm việc với code người khác để lại.
1.2 Test First
Từ h về sau của phần này sẽ nói về test first, và bây giờ hãy bắt đầu với một miêu tả nho nhỏ về đặc điểm quan trọng nhất của nó. Viết test trước khi code làm developer thực sự nghĩ về behavior của object được test, nó đối lập với implementation. Nó loại bỏ implementation xuống mức tối thiểu trong mỗi test case, không còn những đoạn code logic thừa thãi có trong test case nữa. Nó còn giúp tỉ lệ phủ code của bạn rất cao (gần 100%). Cách tiếp cận này có thể được áp dụng ở mọi level của testing, và rất phổ biến cũng như phù hợp với unit test.
2. TDD
TDD = quá trình 3 màu
- Viết 1 test fail (Red)
- Sửa code cho test pass (Green)
- Loại bỏ code dư thừa - clean code (Blue)
2.1 Red
Nghĩ về một vài chức năng sẽ được implement trong code và gọi nó ở trong test. Những chức năng (method) này chưa được implement, cho nên test sẽ fail. Không sao cả, bây giờ bạn đã biết:
- chức năng này không hoạt động đúng.
- một khi nó được implement, nó sẽ được chứng minh là chạy đúng khi test từ red -> green.
Đầu tiên bạn có thể thấy khó chịu khi phải viết test cho những method thậm chí còn chưa được implement. TDD yêu cầu một sự thay đổi nhỏ trong thói quen viết code của bạn, nhưng thỉnh thoảng bạn sẽ thấy cách viết này giúp bạn design code tốt hơn. Bằng việc viết test trước, bạn chuyển từ viết code -> viết API -> tiện lợi cho những người sử dụng. Unit Test của bạn chính là những người dùng đầu tiên của API đó. Đây là những gì TDD thực sự hướng tới: API design.
Khi suy nghĩ với tư cách là người sử dụng đoạn code sắp sửa được viết bởi bạn, bạn nên tập trung vào những thứ gì thật cần thiết. Nên hỏi câu hỏi kiểu như: "có thật sự mình phải viết getter menthod trả về collection này hay sẽ là tiện hơn khi viết method trả về phần tử lớn nhất của collection?". Và bạn cần phải trả lời những câu hỏi như thế này bằng việc viết test. Sẽ không còn những method thực sự không cần thiết và được giữ lại bởi những lý do kiểu như "_biết đâu chúng có thể hữu dụng trong tương la_i", không còn auto-generate getters/setters, một immutable class có thể thích hợp hơn nhiều. Tập trung vào những gì client thực sự cần, và viết test cho chính bọn này, không còn làm gì khác!
Viết test trước, bạn sẽ không thực sự biết implement sẽ như thế nào(thậm chí vài manh mối để implement code). Điều này rất tốt