TDD vs BDD - Tổng quan về hai phương pháp kiểm thử
Phát Triển Phần Mềm
Mục lục
Nói đơn giản, trong TDD, các lập trình viên viết bài kiểm thử trước, sau đó sử dụng kết quả kiểm thử để hướng dẫn quá trình phát triển. Trong khi đó ở BDD, các nhà phát triển mô tả hành vi của hệ thống thông qua cú pháp Gherkin, sau đó lập trình viên sẽ viết mã dựa trên các mô tả đó.
Trong bài viết này, chúng ta sẽ đi sâu vào sự khác biệt giữa TDD và BDD. Mong rằng những thông tin sau sẽ hữu ích đến bạn.
TDD (Test Driven Development) là gì?
TDD là viết tắt của phát triển theo hướng kiểm thử. TDD là một quy trình trong đó lập trình viên viết các bài kiểm thử tự động trước khi viết mã. Kết quả từ các bài kiểm thử này cung cấp thông tin giúp lập trình viên cải thiện mã nguồn của họ. TDD là một phương pháp tiếp cận có tính kỷ luật cao, giúp duy trì phản hồi liên tục để xác định lỗi nhanh hơn và tăng hiệu suất gỡ lỗi.
Làm thế nào để thực hiện TDD?
TDD là một quá trình liên tục và lặp lại để cải thiện mã thông qua các bài kiểm tra. Mục tiêu sau mỗi lần kiểm tra là giúp mã trở nên tốt hơn từng bước một.
Bước 1. Viết Kiểm Tra (Test)
Các lập trình viên bắt đầu quy trình TDD bằng cách viết một bài kiểm tra. Trong bài kiểm tra này, họ xác định cụ thể hành vi hoặc chức năng mong đợi của một đơn vị mã nhỏ, có thể bao gồm:
- Đầu vào mã (các tham số mà mã sẽ nhận được)
- Đầu ra của mã
- Điều kiện tiên quyết/phụ thuộc cần có hoặc phải đúng để thực thi bài kiểm tra
- Các câu lệnh kiểm tra (assertions)
Lập trình viên có thể tự viết kiểm tra bằng ngôn ngữ lập trình hoặc sử dụng các công cụ kiểm thử tự động với tính năng low-code để tăng tốc quá trình viết và thực thi kiểm tra. Cuối cùng, họ phải quyết định nên tự xây dựng một framework kiểm thử hay mua một framework có sẵn từ nhà cung cấp.
Bước 2. Thực Thi Một Bài Kiểm Tra Cụ Thể
Tiếp theo, lập trình viên chạy một bài thử nghiệm cụ thể và quan sát thấy nó thất bại (vì mã vẫn chưa được phát triển ở giai đoạn này). Đây lại là nguyên tắc cốt lõi của TDD. Có 4 lý do chính cho bước này:
- Chạy kiểm tra trên mã chưa hoàn thiện đảm bảo rằng hệ thống kiểm thử, framework và môi trường đang hoạt động đúng. Nếu có bất kỳ vấn đề nào với môi trường thử nghiệm, bạn có thể giải quyết chúng ngay từ đầu.
- Một bài kiểm tra thất bại xác nhận rằng nó thực sự đang kiểm tra hành vi của chức năng mà lập trình viên định triển khai. Đây là một tín hiệu tích cực cho thấy thử nghiệm này đáng tin cậy.
- Thử nghiệm này (và các thử nghiệm trong tương lai được thực hiện) hoạt động như một danh sách kiểm tra hướng dẫn các hoạt động phát triển của bạn. Chúng trở thành mục tiêu để thực hiện, giúp các nhà phát triển tập trung vào việc đáp ứng các yêu cầu và thông số kỹ thuật được nêu trong kế hoạch kiểm tra.
- Khi quy trình lặp lại, bước này cung cấp phản hồi ngay lập tức về độ chính xác của mã, giúp phát hiện và sửa lỗi sớm, giảm thiểu nguy cơ phát sinh vấn đề sau này.
Nói cách khác, một bài kiểm tra thất bại là một bài kiểm tra tốt trong TDD. Câu hỏi quan trọng là: Bài kiểm tra nào nên được thực thi và không đạt trước? Thông thường, ta nên bắt đầu với bài kiểm tra có phạm vi nhỏ, tập trung vào các yêu cầu cốt lõi của tính năng hoặc chức năng cần triển khai.
Bước 3. Triển Khai Mã
Dựa trên kết quả kiểm tra, lập trình viên bắt đầu viết đủ mã. Ở giai đoạn này, mục tiêu không phải là tạo ra một giải pháp hoàn chỉnh hay tối ưu ngay từ đầu, vì bản chất của TDD là sử dụng kết quả kiểm tra để định hướng phát triển, chứ không phải ngược lại. Các nhà phát triển chỉ nên tối ưu hóa mã của họ sau khi nhận được thông tin đầu vào từ các bài kiểm tra.
Điểm đặc biệt của bước này là khuyến khích sự tối giản trong mã nguồn. Mã chỉ cần đáp ứng đúng những gì bài kiểm tra yêu cầu. Các nhà phát triển có thể viết mã ngắn gọn, đi thẳng vào vấn đề và do đó có thể giải quyết các yêu cầu ngay lập tức. Điều này giúp tránh tình trạng tối ưu hóa quá sớm hoặc bổ sung các tính năng không cần thiết (tức là thiết kế quá mức ứng dụng). Đây là một tư duy lành mạnh để đạt được một cơ sở mã tinh gọn dễ hiểu, dễ bảo trì và tái cấu trúc.
Bước 4. Chạy Tất Cả Các Bài Kiểm Tra Và Cải Thiện Mã
Bây giờ chúng ta đã có một số mã mới được thêm vào, các nhà phát triển có thể chạy tất cả các bài kiểm tra còn lại. Trong đó bao gồm cả bài kiểm tra mà họ vừa viết để xác nhận thêm rằng mã mới đang hoạt động tốt và không làm hỏng bất kỳ chức năng nào. Điều này tương tự như kiểm thử hồi quy (regression testing), trong đó các bài kiểm tra được thực hiện để đảm bảo các tính năng vẫn hoạt động bình thường sau khi thay đổi mã.
Với phản hồi từ kiểm tra, lập trình viên có thể tái cấu trúc mã (refactor) để cải thiện thiết kế, tăng tính dễ đọc và bảo trì. Sau đó, chu trình Thất bại - Thành công - Cải thiện lặp lại, được gọi là chu trình Red - Green - Refactor trong TDD.
Lợi ích của TDD
Việc sử dụng Test Driven Development (TDD) mang lại nhiều lợi ích so với các phương pháp phát triển phần mềm truyền thống, bao gồm:
- Giảm thời gian sửa lỗi: TDD không cho phép viết mã mới nếu mã hiện có chưa vượt qua tất cả các bài kiểm tra. Việc viết mã sẽ bị dừng lại cho đến khi mọi lỗi được khắc phục hoàn toàn. Do đó, thời gian dành cho việc làm lại mã bị hỏng được giảm thiểu.
- Phản hồi nhanh chóng: Vì các bài kiểm tra tập trung vào từng phần nhỏ của mã, lập trình viên nhận được phản hồi ngay lập tức, giúp họ có thể thực hiện các điều chỉnh nhanh chóng.
- Tăng năng suất phát triển: TDD ưu tiên tạo ra mã có chức năng rõ ràng hơn là chỉ thiết kế các bài kiểm tra. Do đó, năng suất lập trình được cải thiện và quá trình phát triển trở nên suôn sẻ hơn.
- Mã linh hoạt, dễ bảo trì hơn: Vì mọi phần của mã đều được kiểm thử trước khi chuyển sang phần tiếp theo của quy trình phát triển phần mềm, nên mã vẫn duy trì chức năng và có thể thích ứng trong tương lai.
Ví dụ về phát triển theo hướng kiểm thử
Để hiểu rõ hơn về cách Test Driven Development (TDD) hoạt động trong quá trình phát triển phần mềm, chúng ta có thể xem qua một ví dụ cụ thể.
Giả sử chúng ta cần tạo một lớp Password với điều kiện mật khẩu phải có độ dài từ 5–10 ký tự.
Bước đầu tiên là viết mã để đáp ứng các yêu cầu cần thiết. Sau đó, bạn chạy thử nghiệm để đảm bảo rằng mã hợp lệ. Ví dụ, bạn có thể tạo một lớp kiểm tra độ dài mật khẩu, chạy thử nghiệm và kiểm tra xem đầu ra có đúng với điều kiện đã đặt ra hay không - nghĩa là mật khẩu có nằm trong khoảng 5–10 ký tự hay không. Nếu bài kiểm tra trả về false, bạn có thể điều chỉnh lại mã để đáp ứng yêu cầu.
BDD (Behavior Driven Development) là gì?
Nói một cách đơn giản, BDD (Behavior Driven Development) là một phương pháp kiểm thử trong Agile. Trong đó hành vi của hệ thống được sử dụng để định hướng hoạt động phát triển. Thay vì bắt đầu với bài kiểm thử như trong TDD, BDD bắt đầu bằng việc phân tích hành vi mong muốn mà các nhà phát triển muốn tạo ra. Sau đó, họ diễn đạt hành vi đó bằng cú pháp Gherkin, bao gồm các câu lệnh Given - When - Then. Những câu lệnh này giúp lập trình viên biết cách phát triển mã để đáp ứng các hành vi đã mô tả.
Làm thế nào để thực hiện BDD?
Các bước để phát triển theo hành vi khá đơn giản và có thể lặp lại khi cần thiết:
Bước 1. Viết kịch bản bằng Gherkin
Ở giai đoạn này, các bên liên quan, tester và developer sẽ cùng nhau thu thập yêu cầu và xác định kết quả mong muốn. Họ sẽ sử dụng ngôn ngữ Gherkin để mô tả các hành vi của hệ thống. Gherkin bao gồm các câu lệnh Given - When - Then, mỗi câu lệnh mô tả một khía cạnh cụ thể của hệ thống.
Bước 2. Áp dụng TDD
TDD có thể được sử dụng như một phương pháp độc lập hoặc kết hợp với BDD. Sau khi các câu lệnh Gherkin được viết ra, các nhà phát triển có thể bắt đầu triển khai các bài kiểm thử tự động dựa trên chúng. Tùy vào ngôn ngữ lập trình hoặc công nghệ của công ty, các nhà phát triển có thể lựa chọn các framework kiểm thử BDD như Cucumber, Behat, SpecFlow.
Lần chạy kiểm thử đầu tiên thường sẽ thất bại, nhưng dựa vào đó, các lập trình viên có thể xác định hướng phát triển phù hợp. Sau khi tính năng được triển khai, ta có thể chạy lại các kịch bản kiểm thử tự động BDD để xác nhận rằng tính năng đã hoàn thiện. Quy trình này lặp đi lặp lại cho đến khi ứng dụng được phát triển đầy đủ.
Điểm đặc biệt của BDD là nó giúp chuyển đổi những yêu cầu kỹ thuật phức tạp thành ngôn ngữ dễ hiểu. Ngay cả những người không chuyên về kỹ thuật cũng có thể tham gia và đóng góp vào dự án. BDD thúc đẩy sự hợp tác và giảm thiểu hiểu lầm giữa các bên liên quan.
Lợi ích của BDD
Việc áp dụng BDD vào phát triển phần mềm mang lại nhiều lợi ích, bao gồm:
- Tích hợp trải nghiệm người dùng: BDD tập trung vào trải nghiệm của người dùng. Nhờ đó, đội ngũ phát triển có cái nhìn tổng thể hơn và xác định những khoảng trống trong hiểu biết của họ.
- Hiệu quả về chi phí: Vì BDD đặt ra các ưu tiên cho người dùng, nhà phát triển và nhà đầu tư, nên nó cho phép sử dụng tài nguyên một cách tối ưu trong quá trình phát triển chương trình.
- Kiểm tra đa trình duyệt đơn giản: BDD tập trung vào hành vi, nghĩa là nó cung cấp cho bạn một khuôn khổ lý tưởng để kiểm tra đa trình duyệt.
TDD và BDD khác nhau như thế nào?
Sự khác biệt cốt lõi giữa TDD và BDD nằm ở đối tượng kiểm thử và cách thức thực hiện. BDD chủ yếu tập trung vào hành vi ứng dụng từ góc nhìn của người dùng cuối, trong khi TDD kiểm thử từng phần nhỏ của chức năng một cách độc lập.
Ngoài ra, BDD yêu cầu sự tham gia của nhiều bên liên quan như quản lý dự án, nhà phát triển và kỹ sư kiểm thử để cùng nhau xây dựng các kịch bản hành vi. Do đó, cần phải có rất nhiều sự giao tiếp trước khi bất kỳ điều gì được triển khai. Mặt khác, TDD có thể được thực hiện bởi một nhà phát triển duy nhất mà không cần đầu vào bên ngoài từ các nhà quản lý dự án hoặc các bên liên quan.
Khía cạnh | Test-Driven Development (TDD) | Behavior-Driven Development (BDD) |
Phương pháp |
Triển khai chức năng của mã thông qua phương pháp kiểm thử trước |
Hợp tác, hiểu biết chung và xác thực hành vi hệ thống từ góc nhìn của người dùng |
Thuật ngữ & khả năng đọc |
Các trường hợp kiểm thử được viết bằng thuật ngữ lập trình |
Các kịch bản được viết bằng ngôn ngữ tự nhiên, dễ hiểu với cả thành viên nhóm kỹ thuật và không chuyên |
Hợp tác |
Hợp tác giữa nhà phát triển và tester |
Hợp tác giữa nhà phát triển, tester và các bên liên quan để xác định và xác thực hành vi hệ thống |
Mức độ trừu tượng |
Tập trung vào kiểm thử đơn vị cấp thấp để xác minh hành vi của từng phần mã nhỏ |
Tập trung vào kiểm thử cấp cao hơn, mô phỏng tương tác của người dùng hoặc các kịch bản từ đầu đến cuối |
Cách tổ chức kiểm thử |
Kiểm thử được tổ chức theo cấu trúc mã và cách tiếp cận phân cấp hoặc mô-đun |
Các kịch bản được tổ chức xung quanh hành vi mong muốn, thường được nhóm theo các tính năng hoặc chức năng cụ thể |
Mục đích | Đảm bảo tính chính xác của mã thông qua kiểm thử tự động | Thúc đẩy sự hiểu biết chung, giao tiếp và xác thực hành vi hệ thống |
Quy trình phát triển |
Viết kiểm thử trước khi triển khai mã tương ứng |
Các kịch bản được xác định theo cách cộng tác trước khi triển khai mã. Có thể triển khai TDD trong BDD |
Phạm vi kiểm thử |
Phạm vi hẹp, tập trung vào từng đơn vị mã riêng lẻ |
Phạm vi rộng, bao gồm nhiều đơn vị mã làm việc cùng nhau |
Phong cách kiểm thử | Tập trung vào kỹ thuật và triển khai | Tập trung vào người dùng và hành vi hệ thống |
Độ chi tiết của kiểm thử |
Chi tiết cao, kiểm thử các đơn vị mã riêng lẻ trong môi trường biệt lập |
Ít chi tiết hơn, kiểm thử hành vi của hệ thống như một tổng thể |
Cải tiến và phản hồi liên tục | Liên tục tinh chỉnh mã thông qua các lần kiểm thử thất bại và sửa đổi mã sau đó | Liên tục tinh chỉnh kịch bản kiểm thử và hành vi thông qua hợp tác và phản hồi |
Kết luận
Cả TDD (Test Driven Development) và BDD (Behavior Driven Development) đều là những phương pháp kiểm thử mạnh mẽ giúp nâng cao chất lượng phần mềm và tối ưu hóa quy trình phát triển.
Việc lựa chọn giữa TDD và BDD phụ thuộc vào mục tiêu của dự án, mô hình làm việc của nhóm phát triển và mức độ ưu tiên của kiểm thử. Trong nhiều trường hợp, việc kết hợp cả hai phương pháp có thể mang lại hiệu quả tối ưu, vừa đảm bảo mã nguồn chất lượng cao vừa đáp ứng được yêu cầu thực tế từ người dùng.