TEST-DRIVEN DEVELOPMENT
Trong những năm gần đây, khái niệm TDD được đưa ra dựa trên mô hình phát triển PM khá nổi tiếng XP (Extreme Programming). TDD là một chiến lược phát triển sử dụng kỹ thuật UT theo nguyên tắc tạo ra các công đoạn kiểm nghiệm trước khi xây dựng mã.
Ý tưởng chính của TDD: Trước khi bạn bắt tay viết mã, hãy nghĩ về những gì phải làm trước. Không giống như lập trình truyền thống, trong TDD chúng ta viết mã kiểm tra trước khi viết mã chính, chỉ được viết sau khi đạt đủ số lượng UT cần thiết cho các tình huống có thể xảy ra.
Có thể hiểu TDD là một quy trình vòng tròn bắt đầu bởi các UT với trạng thái đầu tiên là "fail", tiếp theo cần viết mã để các UT chuyển trạng thái "pass", và cuối cùng hiệu chỉnh mã cho đơn giản hơn. Quy trình này được tái diễn liên tục đối với mọi đơn vị chương trình cho đến khi kết thúc hoàn toàn dự án.
Đặc điểm của TDD
• Là quy trình phát triển tăng dần theo kịch bản và gắn chặt với các công đoạn kiểm nghiệm trước khi đưa ứng dụng vào vận hành thực sự.
• Là phương pháp phát triển PM ở đó áp dụng kỹ thuật UT tiến hành kiểm tra tất cả các interface, tạo ra các MO cần thiết mô phỏng sự vận hành của ứng dụng ở một nơi riêng biệt.
• Tạo ra bộ khung vận hành tự động cho tất cả các thao tác kiểm nghiệm bộ phận trong hệ thống mỗi khi xây dựng một phiên bản mới.
Lợi ích của TDD
• TDD là một kỹ thuật giúp định hình ý tưởng thiết kế hơn là kiểm nghiệm mã chương trình. Thực hiện theo TDD sẽ làm sáng tỏ thêm các yêu cầu bài toán, giải tỏa sự bế tắc trong khi đi tìm giải pháp, phát hiện sớm các vấn đề về thiết kế và tránh được những công việc phải làm lại.
• TDD là một phần bổ trợ không thể thiếu trong các công việc lập trình theo nhóm nhỏ, thường là hai người cùng phát triển một module. Trong mô hình này, luân phiên một người có nhiệm vụ nghĩ về tình huống kiểm tra tiếp theo, viết UT cho tình huống và các MO cần thiết. Người còn lại tập trung viết mã để các UT chuyển sang trạng thái "pass"; giúp giảm thiểu lỗi so với khi làm việc độc lập.
• TDD định hướng cho nhóm thiết kế vận dụng tốt các phương pháp hướng đối tượng (các đối tượng cần kiểm tra phải thực thi một interface là một thí dụ), đặc biệt có thể thu được thiết kế tốt theo hai nguyên tắc:
- Loosely-Coupled: Bất kỳ sự thay đổi nào cũng đều không ảnh hưởng đến các đối tượng khác.
- Highly-Cohesive: Có tính chất khép kín theo nghĩa chỉ thực hiện những chức năng gần với nhau về mặt nghiệp vụ và thiết kế, đồng thời loại ra những chức năng ít có liên quan đến các chức năng chính.
• Lợi ích quan trọng cuối cùng của TDD là xây dựng các đoạn mã chất lượng và an toàn, tập trung hơn, giảm phân mảnh mã và giảm rủi ro xảy ra ngoài dự kiến.
Trong TDD, càng nhiều UT được tạo ra thì càng có nhiều khả năng khống chế nhanh chóng các lỗi nghiêm trọng xảy ra. Các UT càng "mịn" theo nghĩa không thể chia nhỏ hoặc không thể bổ sung được nữa thì khả năng đáp ứng yêu cầu kiểm nghiệm càng cao. Khi đã thiết kế đủ các UT có khả năng phát hiện chính xác bất kỳ một lỗi kỹ thuật nào, chúng ta có thể yên tâm chuyển giao module cho chuyên viên QA kiểm định chức năng (functional testing). Tuy nhiên trong suốt giai đoạn phát triển sau đó cần kiểm tra định kỳ các trạng thái của UT để đảm bảo việc cập nhật không phá vỡ tính đúng đắn của các đoạn mã cũ.
Quy trình thực hiện
Trình tự thực hiện trong TDD như sau:
1. Đối với một module, nghĩ về các công việc sẽ làm và cách kiểm tra công việc đó như thế nào.
2. Tạo test suite ứng với module đó.
3. Bắt tay thiết kế sơ bộ tất cả các UT có thể nghĩ ra. Bước này thực chất là thu thập các tình huống có thể phát hiện lỗi vào một danh sách công việc cần kiểm nghiệm.
4. Viết mã để đảm bảo các UT được biên dịch.
5. Thực thi các UT, vì mã chính của module chưa tồn tại nên trạng thái là "fail".
6. Viết mã cho module để thay đổi trạng thái UT, có thể bổ sung UT nếu cần thiết.
7. Chạy lại toàn bộ test suite và quan sát các UT lỗi, lặp lại bước 6-7 cho đến khi tất cả UT đều đạt trạng thái "pass".
8. Hiệu chỉnh mã để loại bỏ các phần lặp lại, các khối mã và các phân nhánh, liên kết thiếu hợp lý hoặc các khối mã không còn hoạt động... đồng thời viết chú giải các phần quan trọng. Hãy thực hiện công việc này thường xuyên vì chúng ta sẽ không có thời gian quay lại cho công việc hiệu chỉnh.
Bước cuối cùng có ý nghĩa rất lớn trong việc giảm sự phụ thuộc vào các module khác và gia tăng sự độc lập về mặt nghiệp vụ của module hiện hành. Cần lưu ý kiểm tra lại trạng thái tất cả các UT sau mỗi lần hiệu chỉnh vì rất có thể công việc này sẽ gây ra lỗi ở đâu đó.
Chiến lược phát triển với TDD
Mỗi công ty PM đều có cách điều hành quản lý phát triển PM khác nhau, nhưng tất cả đều có chung một mục đích là giảm số lỗi xuống mức nhỏ nhất có thể và khống chế lỗi phát sinh trở lại. Tuy nhiên nhìn chung một quy trình phát triển PM lý tưởng không thể thiếu các bước quan trọng sau đây:
• Thiết kế một dự án thử nghiệm riêng, độc lập, tách biệt với khu vực phát triển. Không gắn dự án thử nghiệm đó vào phiên bản sản phẩm được giao cho khách hàng, vì điều này có thể làm tăng kích thước sản phẩm.
• Xây dựng một cơ sở dữ liệu các test suite cho mọi module phục vụ việc kiểm nghiệm cả hai khía cạnh phát triển và chức năng.
• Chia nhỏ dự án ra nhiều quy trình nhỏ hơn dựa trên ngữ cảnh, giúp việc viết UT được dễ dàng hơn. Để kiểm tra hiệu quả của toàn bộ ứng dụng, tốt nhất là kiểm tra hiệu quả của mọi đơn vị mã nhỏ nhất.
• Có thể thiết lập các cơ sở dữ liệu riêng cho dự án thử nghiệm lưu trữ tất cả các giá trị đầu vào và các kết quả trả về mong muốn... XML sẽ là cách tiếp cận tốt nhất cho những cơ sở dữ liệu loại này.
• Tích hợp công việc kiểm nghiệm thành một phần trong quy trình tự động hoá quản lý mã nguồn như tích hợp toàn bộ công việc, biên dịch vào cuối ngày làm việc... Mỗi một công việc như vậy được gọi là một "build". Về quy trình này có thể tham khảo ứng dụng nguồn mở Ant trong Java (hoặc NAnt cho .NET), hay các công cụ thương mại như CruiseControl hoặc Anthill.
• Cuối cùng thay vì kiểm nghiệm bằng tay, hãy để máy tính thực hiện tự động và gửi báo cáo cho bạn. Các thông báo email tự động hàng ngày về tình trạng của các UT sẽ luôn đảm bảo cho dự án thông suốt. Tất cả các công việc này có thể được tiến hành trên một máy tính riêng có khả năng kiểm soát các thay đổi mã nguồn.
Nguồn: pcworld.com.vn
Ý tưởng chính của TDD: Trước khi bạn bắt tay viết mã, hãy nghĩ về những gì phải làm trước. Không giống như lập trình truyền thống, trong TDD chúng ta viết mã kiểm tra trước khi viết mã chính, chỉ được viết sau khi đạt đủ số lượng UT cần thiết cho các tình huống có thể xảy ra.
Có thể hiểu TDD là một quy trình vòng tròn bắt đầu bởi các UT với trạng thái đầu tiên là "fail", tiếp theo cần viết mã để các UT chuyển trạng thái "pass", và cuối cùng hiệu chỉnh mã cho đơn giản hơn. Quy trình này được tái diễn liên tục đối với mọi đơn vị chương trình cho đến khi kết thúc hoàn toàn dự án.
Đặc điểm của TDD
• Là quy trình phát triển tăng dần theo kịch bản và gắn chặt với các công đoạn kiểm nghiệm trước khi đưa ứng dụng vào vận hành thực sự.
• Là phương pháp phát triển PM ở đó áp dụng kỹ thuật UT tiến hành kiểm tra tất cả các interface, tạo ra các MO cần thiết mô phỏng sự vận hành của ứng dụng ở một nơi riêng biệt.
• Tạo ra bộ khung vận hành tự động cho tất cả các thao tác kiểm nghiệm bộ phận trong hệ thống mỗi khi xây dựng một phiên bản mới.
Lợi ích của TDD
• TDD là một kỹ thuật giúp định hình ý tưởng thiết kế hơn là kiểm nghiệm mã chương trình. Thực hiện theo TDD sẽ làm sáng tỏ thêm các yêu cầu bài toán, giải tỏa sự bế tắc trong khi đi tìm giải pháp, phát hiện sớm các vấn đề về thiết kế và tránh được những công việc phải làm lại.
• TDD là một phần bổ trợ không thể thiếu trong các công việc lập trình theo nhóm nhỏ, thường là hai người cùng phát triển một module. Trong mô hình này, luân phiên một người có nhiệm vụ nghĩ về tình huống kiểm tra tiếp theo, viết UT cho tình huống và các MO cần thiết. Người còn lại tập trung viết mã để các UT chuyển sang trạng thái "pass"; giúp giảm thiểu lỗi so với khi làm việc độc lập.
• TDD định hướng cho nhóm thiết kế vận dụng tốt các phương pháp hướng đối tượng (các đối tượng cần kiểm tra phải thực thi một interface là một thí dụ), đặc biệt có thể thu được thiết kế tốt theo hai nguyên tắc:
- Loosely-Coupled: Bất kỳ sự thay đổi nào cũng đều không ảnh hưởng đến các đối tượng khác.
- Highly-Cohesive: Có tính chất khép kín theo nghĩa chỉ thực hiện những chức năng gần với nhau về mặt nghiệp vụ và thiết kế, đồng thời loại ra những chức năng ít có liên quan đến các chức năng chính.
• Lợi ích quan trọng cuối cùng của TDD là xây dựng các đoạn mã chất lượng và an toàn, tập trung hơn, giảm phân mảnh mã và giảm rủi ro xảy ra ngoài dự kiến.
Trong TDD, càng nhiều UT được tạo ra thì càng có nhiều khả năng khống chế nhanh chóng các lỗi nghiêm trọng xảy ra. Các UT càng "mịn" theo nghĩa không thể chia nhỏ hoặc không thể bổ sung được nữa thì khả năng đáp ứng yêu cầu kiểm nghiệm càng cao. Khi đã thiết kế đủ các UT có khả năng phát hiện chính xác bất kỳ một lỗi kỹ thuật nào, chúng ta có thể yên tâm chuyển giao module cho chuyên viên QA kiểm định chức năng (functional testing). Tuy nhiên trong suốt giai đoạn phát triển sau đó cần kiểm tra định kỳ các trạng thái của UT để đảm bảo việc cập nhật không phá vỡ tính đúng đắn của các đoạn mã cũ.
Quy trình thực hiện
Trình tự thực hiện trong TDD như sau:
1. Đối với một module, nghĩ về các công việc sẽ làm và cách kiểm tra công việc đó như thế nào.
2. Tạo test suite ứng với module đó.
3. Bắt tay thiết kế sơ bộ tất cả các UT có thể nghĩ ra. Bước này thực chất là thu thập các tình huống có thể phát hiện lỗi vào một danh sách công việc cần kiểm nghiệm.
4. Viết mã để đảm bảo các UT được biên dịch.
5. Thực thi các UT, vì mã chính của module chưa tồn tại nên trạng thái là "fail".
6. Viết mã cho module để thay đổi trạng thái UT, có thể bổ sung UT nếu cần thiết.
7. Chạy lại toàn bộ test suite và quan sát các UT lỗi, lặp lại bước 6-7 cho đến khi tất cả UT đều đạt trạng thái "pass".
8. Hiệu chỉnh mã để loại bỏ các phần lặp lại, các khối mã và các phân nhánh, liên kết thiếu hợp lý hoặc các khối mã không còn hoạt động... đồng thời viết chú giải các phần quan trọng. Hãy thực hiện công việc này thường xuyên vì chúng ta sẽ không có thời gian quay lại cho công việc hiệu chỉnh.
Bước cuối cùng có ý nghĩa rất lớn trong việc giảm sự phụ thuộc vào các module khác và gia tăng sự độc lập về mặt nghiệp vụ của module hiện hành. Cần lưu ý kiểm tra lại trạng thái tất cả các UT sau mỗi lần hiệu chỉnh vì rất có thể công việc này sẽ gây ra lỗi ở đâu đó.
Chiến lược phát triển với TDD
Mỗi công ty PM đều có cách điều hành quản lý phát triển PM khác nhau, nhưng tất cả đều có chung một mục đích là giảm số lỗi xuống mức nhỏ nhất có thể và khống chế lỗi phát sinh trở lại. Tuy nhiên nhìn chung một quy trình phát triển PM lý tưởng không thể thiếu các bước quan trọng sau đây:
• Thiết kế một dự án thử nghiệm riêng, độc lập, tách biệt với khu vực phát triển. Không gắn dự án thử nghiệm đó vào phiên bản sản phẩm được giao cho khách hàng, vì điều này có thể làm tăng kích thước sản phẩm.
• Xây dựng một cơ sở dữ liệu các test suite cho mọi module phục vụ việc kiểm nghiệm cả hai khía cạnh phát triển và chức năng.
• Chia nhỏ dự án ra nhiều quy trình nhỏ hơn dựa trên ngữ cảnh, giúp việc viết UT được dễ dàng hơn. Để kiểm tra hiệu quả của toàn bộ ứng dụng, tốt nhất là kiểm tra hiệu quả của mọi đơn vị mã nhỏ nhất.
• Có thể thiết lập các cơ sở dữ liệu riêng cho dự án thử nghiệm lưu trữ tất cả các giá trị đầu vào và các kết quả trả về mong muốn... XML sẽ là cách tiếp cận tốt nhất cho những cơ sở dữ liệu loại này.
• Tích hợp công việc kiểm nghiệm thành một phần trong quy trình tự động hoá quản lý mã nguồn như tích hợp toàn bộ công việc, biên dịch vào cuối ngày làm việc... Mỗi một công việc như vậy được gọi là một "build". Về quy trình này có thể tham khảo ứng dụng nguồn mở Ant trong Java (hoặc NAnt cho .NET), hay các công cụ thương mại như CruiseControl hoặc Anthill.
• Cuối cùng thay vì kiểm nghiệm bằng tay, hãy để máy tính thực hiện tự động và gửi báo cáo cho bạn. Các thông báo email tự động hàng ngày về tình trạng của các UT sẽ luôn đảm bảo cho dự án thông suốt. Tất cả các công việc này có thể được tiến hành trên một máy tính riêng có khả năng kiểm soát các thay đổi mã nguồn.
Nguồn: pcworld.com.vn
Nhận xét
Đăng nhận xét