CHƯƠNG 1. KIỂM THỬ TRONG PHƯƠNG PHÁP PHÁT TRIỂN PHẦN MỀM LINH HOA ̣T
1.4. Các kỹ thuâ ̣t phát triển phần mềm theo hướng kiểm thử
1.4.1. Phát triển phần mềm theo hướng kiểm thử
Phát triển phần mềm theo hướng kiểm thử (Test-Driven Development- TDD) là yếu tố cơ bản trong các quy trình phát triển phần mềm theo phương pháp phát triển linh hoạt Agile nhằm đáp ứng sự thay đổi yêu cầu người dùng trong quá trình cài đặt phần mềm, đólà một phương pháp tiếp cận cải tiến để phát triển phần mềm, trong đó kết hợp phương pháp phát triển kiểm thử trước (Test First Development) và phương pháp điều chỉnh lại mã nguồn (Refactoring). Mục tiêu của TDD là viết mã nguồn sáng sủa, rõ ràng và có thể chạy đƣợc.Nguyên lý làm việc của TDD theo 3 điểm chính nhƣHình 1-4:
Viết các hàm kiểm thử , ban đầu đă ̣t chúng ở trạng thái thất bại: Trước khi viết mã cài đă ̣t mô ̣t chƣ́c năng , các lập trình viên sẽ tạo ra một kiểm thử đơn vị
mô tả cách mà chức năng đó sẽ đƣợc cài đặt theo đúng tài liệu yêu cầu. Kiểm thử này ban đầu ở trạng thái thất ba ̣i.
Cài đặt mã nguồn chương trình để kiểm thử đó thành công :Sau khi có
hàm kiểm thử , lâ ̣p trình viên tiến hành cài đă ̣t cho chƣ́c năng đó càng nhanh càng tốt. Viê ̣c viết mã nguồn được thực hiện cho tới khi các kiểm thử tương ứng ở trạng thái thành công.
Điều chỉnh mã nguồn: Sau khi hoàn thiê ̣n giai đoa ̣n cài đă ̣t mã nguồn cho chƣ́c năng, lâ ̣p trình viên cần loại bỏ các phần mã cài đặt bịtrùng lặp hoặc không phù hợp nhằm làm cho mã nguồn ƣ́ng du ̣ng sáng sủa, rõ ràng hơn.
Hình 1-4. Nguyên lý TDD
Phát triển phần mềm dựa vào kiểm thử thay đổi hoàn toàn so với cách phát triển phần mềm theo phương pháp truyền thống. Trong phương pháp này , khi bắt đầu thực hiện một tính năng mới, câu hỏi đầu tiên đặt ra là liệu thiết kế hiện tại có phải là thiết kế tốt nhất cho phép lập trình viên thực hiện các chức năng hay không? Nếu có, tiến hành thực hiện thông qua một phương pháp phát triển kiểm thử trước. Nếu không, nhà phát triển cần điều chỉnh lại nó một cách cục bộ để thay đổi riêng phần thiết kế bị ảnh hưởng bởi tính năng mới, điều này giúp dễ dàng bổ sung thêm các tính năng còn thiếu sót, nâng cao chất lƣợng của thiết kế.
Vòng đời của một dự án áp dụng quy TDD đƣợc mô tả nhƣ Hình 1-5 gồm các bước sau:
a. Thêm một kiểm thử
Trong phương pháp phát triển hướng kiểm thử TDD , phát triển một tính năng mới bắt đầu bằng viê ̣c viết mô ̣t kiểm thƣ̉ , trạng thái của kiểm thử này ban đầu được đă ̣t là thất ba ̣i vì chưa có mã nguồn cài đă ̣t tương ứng. Dựa vào đă ̣c tả
yêu cầu, các trường hợp sử dụng, các tiêu chí kiểu thử chấp nhận của câu chuyện người dùng, lâ ̣p trình viên phải hiểu , bao quát được yêu cầu và các trường hợp
ngoại lệ để có thể viết kiểm thử cho nó. Các phương thức kiểm thử thường được viết với sự hỗ trợ của công cu ̣ phù hợp với môi trường phát triển phần mềm.
Hình 1-5. Vòng đời của phần mềm phát triển theo TDD b. Thực hiê ̣n và kiểm tra trạng thái tất cả các kiểm thử
Sau khi thực hiê ̣n xong bước viết kiểm thử , lâ ̣p trình viên sẽ phải thực hiê ̣n các kiểm thử đó để kiểm tra độ tin cậy . Phải đảm bảo các kiểm thử mới đƣợc viết và chư a có mã nguồn cài đă ̣t tương ứng luôn ở tra ̣ng thái thất ba ̣i và mô ̣t kiểm thử được đánh dấu là thành công thì ít nhất tính năng tương ứng với kiểm thử đó p hải được cài đặt . Giai đoa ̣n này thường được sử du ̣ng với các côn g cu ̣ kiểm thƣ̉ tƣ̣ đô ̣ng.
c. Cài đặt mã nguồn
Sau khi viết các kiểm thƣ̉ mới và đảm bảo kiểm thƣ̉ đó ở tra ̣ng thái thất ba ̣i , lâ ̣p trình viên tiến hành cài đặt mã nguồn cho tính năng tương ứng cho đến khi kiểm thƣ̉ đó thành công. Mục đích chính của giai đoạn này là làm cho các kiểm thử từ tra ̣ng thái thất ba ̣i chuyển sang thành công , do đó mã nguồn được cài đă ̣t có thế chƣa phải là hoàn toàn phù hợp , chúng có thể đƣợc cả i tiến, tinh chỉnh ở
giai đoa ̣n sau.
d. Thực hiê ̣n các kiểm thử
Giai đoa ̣n này nhằm mu ̣c đích để lâ ̣p trình viên biết tra ̣ng thái phát triển của hê ̣ thống. Nếu còn tồn ta ̣i phương thức kiểm thử ở tra ̣ng thái thất ba ̣i thì lâ ̣p trình viên phải tiến hà nh rà soát , cài đặt mã nguồn cho tính năng đó . Nếu tra ̣ng thái
của tất cả các kiểm thử đều thành công thì có thể đảm bảo rằng phần mã nguồn được cài đă ̣t đáp ứng các yêu cầu kiểm thử.
e. Điều chỉnh mã nguồn
Viê ̣c cài đ ặt mã nguồn cho các tính năng mới luôn luôn được bổ sung vào quá trình phát triển để các kiểm thử đã viết chuyển tƣ̀ tra ̣ng thái thất ba ̣i sang thành công. Điều này cũng dẫn đến một thực tế là một các mã nguồn đã cài đă ̣t có thể dƣ thừa hoă ̣c chƣa thƣ̣c sƣ̣ tối ƣu, lúc này lâ ̣p trình viên sẽ phải điều chỉnh lại phần mã nguồn đã đƣợc viết nhằm giảm thiểu sự trùng lặp và làm cho mã nguồn sáng sủa, dễ hiểu.
Quá trình trên đƣợc lặp đi lặ p la ̣i cho đến khi thƣ̣c hiê ̣n xong các yêu cầu của ứng dụng. TDD thường được sử du ̣ng trong các quy trình phần mềm lă ̣p và
nó là một kỹ thuật nhằm đảm bảo toàn bộ mã nguồn của hệ thống đƣợc kiểm thử mức đơn vị. Tuy nhiên, thực hiện tốt mức kiểm thử đơn vị chƣa đảm bảo đƣợc dự án thành công và không có lỗi trong quá trình vận hành. Do đó, khi sử dụng TDD vẫn cần xem xét các kỹ thuật kiểm thử khác nhƣ kiểm thử chấp nhận hay kiểm thử dò hỏi, …
Trong kiểm thử truyền thống, một ca kiểm thử thành công khi nó phát hiện ra một hoặc nhiều lỗi chương trình. Tương tự với TDD, khi một mẫu kiểm thử thất bại giúp lập trình viên biết phải cải thiện lại phần mã của mình. TDD giúp tăng độ tin cậy của hệ thống đang phát triển.
Trong phương pháp kiểm thử truyền thống, hệ thống càng có nhiều rủi ro lớn càng cần phải có nhiều mẫu kiểm thử đƣợc thực hiện, nhƣng việc đảm bảo kiểm thử hết tất cả các hàm, các đường đi của mã nguồn rất khó thực hiện. Trong khi đó, sử dụng TDDđảm bảo kiểm thử độ phủ mã nguồn đạt gần nhƣ 100% - mọi dòng mã đều đƣợc kiểm thử, điều này giúp tăng độ tin cậy của kiểm thử đơn vị. Không có gì ngạc nhiên khi nói rằng TDD là một kỹ thuật đặc tả với một tác dụng phụ có giá trị là nó đem lại kết quả trong việc kiểm thử mã nguồn tốt hơn đáng kể so với các kỹ thuật truyền thống.
Ưu điểm của TDD:
Một lợi thế đáng kể của TDD là nó cho phép thực hiện các bước nhỏ khi viết phần mềm.Đây là một lợi thế đã phát huy trong nhiều năm quabởi vì nó mang lại hiệuquả cao hơn so viếtmã trong những bước lớn. Chẳng ha ̣n như , khi lâ ̣p trình viên cần viết mã cho mô ̣t chƣ́c năng mới , sau đó biên di ̣ch và kiểm thƣ̉ thì khả năng rất lớn là kiểm thƣ̉ đó sẽ bi ̣ thất bại bởi nhƣ̃ng lỗi phát sinh trong phần mã nguồn vừa bổ sung . Trong trường hợp này , viê ̣c thực hiê ̣n các
bước nhỏ phát huy tác du ̣ng bởi viê ̣c kiểm tra vài dòng mã dễ dàng hơn rất nhiều viê ̣c kiểm tra vài nghìn dòng mã.
Nhiều người cho rằng các kỹ thuật trong phương pháp phát triển linh hoạt Agile hoạt động rất ổn với những dự án nhỏ, cần một số ít người trong một vài tháng, nhƣng với những dự án lớn thì Agile có nhiều hạn chế. Tuy nhiên, thƣ̣c tế
thì điều này không hoàn toàn đúng, có những hệ thống Smalltalk sử dụng hoàn toàn phương pháp hướng kiểm thửđể thực hiện trong thời gian 4 năm với chi phí nhân công 40 man-year, ra kết quả gồm 250,000 dòng mã cho các chức năng và 250,000 dòng mã kiểm thử. Có 4000 mẫu kiểm thử chạy dưới 20 phút, còn với bộ mẫu kiểm thử đầy đủ thì cần chạy vài ngày. Điều đó chứng tỏ rằng TDD vẫn hoạt động tốt với những dự án có kích thước lớn.
Các công cụ phục vụ cho TDD, thường là các nền tảng cho kiểm thử mã nguồn mức đơn vị, chẳng hạn nhƣ: cppUnit, csUnit (.Net), CUnit, DUnit (Delphi), DBFit, DBUnit, HTMLUnit, HTTPUnit, JMock, JUnit, NDbUnit, NUnit, OUnit, PHPUnit, PyUnit (Python), SimpleTest, TestNG, Test::Unit (Ruby), VBUnit, XTUnit.
Thiết kế dựa trên kiểm thử là một kỹ thuật phát triển phần mềm, trong đó trước tiên lập trình viên phải viết một mã kiểm thử chạy thất bại, trước khi viết mã nguồn cho chức năng mới. TDD đang nhanh chóng đƣợc nhiều công tysản xuất phần mềm theo phương pháp linh hoạt Agile sử dụng để phát triển mã nguồn ứng dụng, và thậm chí còn đƣợc thông qua bởi những nhà quản trị cơ sở dữ liệu theo phương pháp Agile để phát triển cơ sở dữ liệu. TDD không thay thế phương pháp kiểm thử truyền thống, thay vào đó nó định nghĩa một cách thức để đảm bảo việc thực hiện các kiểm thử đơn vị một cách hiệu quả. Hiệu ứng phụ của TDD là các kiểm thử cung cấp một đặc tả hoạt động cho mã nguồn, thông qua đó lâ ̣p trình viên có thể hiều mình các công viê ̣c , các đoạn mã cần cài đặt cho tính năng tương ứng.