Kiểm thử đơn vị tham số hóa còn đang là một khái niệm mới mẻ đối với nhiều nhà phát triển phần mềm.
ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ Trần Bình Dương SINH CA KIỂM THỬ THAM SỐ HÓA CHO CHƯƠNG TRÌNH JAVA KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY Ngành: Công Nghệ Thông Tin HÀ NỘI - 2009 ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ Trần Bình Dương SINH CA KIỂM THỬ THAM SỐ HÓA CHO CHƯƠNG TRÌNH JAVA KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY Ngành: Công Nghệ Thông Tin Cán bộ hướng dẫn: TS. Trương Anh Hoàng LỜI CẢM ƠN Lời đầu tiên em xin được gửi lời cảm ơn chân thành tới TS. Trương Anh Hoàng, người thầy đáng kính đã tận tình hướng dẫn em trong suốt thời gian thực hiện khóa luận này. Em cũng muốn bày tỏ lòng biết ơn đến các thầy cô giáo trường Đại học Công Nghệ - Đại học Quốc Gia Hà nội, đặc biệt là các thầy cô trong khoa công nghệ thông tin đã tận tình dạy dỗ và tạo mọi điều kiện học tập thuận lợi cho em trong suốt bốn năm học qua. Cuối cùng, em xin gửi lời cảm ơn tới gia đình đình em. Nếu không có tình yêu, sự ủng hộ và động viên từ gia đình thì em sẽ không thể hoàn thành khoá luận và có được những kết quả như ngày hôm nay. Hà nội, 05/2009 Sinh viên Trần Bình Dương i TÓM TẮT NỘI DUNG Kiểm thử đơn vị tham số hóa còn đang là một khái niệm mới mẻ đối với nhiều nhà phát triển phần mềm. Kiểm thử đơn vị tham số hóa đang dần đóng một vài trò hết sức quan trọng trong phát triển phần mềm. Khóa luận này ra đời chính là để nghiên cứu về phương pháp kiểm thử mới này và ứng dụng nó cho mục đích kiểm thử các chương trình Java. Nội dung khóa luận tập trung vào việc áp dụng khả năng của một nền kiểm chứng Java bytecode mã nguồn mở rất hiệu quả và phổ biến hiện nay là Java PathFinder để xây dựng một hệ thống hỗ trợ kiểm thử đơn vị tham số hóa cho mục đích kiểm thử các chương trình Java. Kết quả của khóa luận là đã xây dựng được một hệ thống để thực thi các ca kiểm thử đơn vị tham số hóa viết cho các chương trình Java đơn giản. Bên cạnh đó, khóa luận cũng đã trình bày một cách sâu sắc về kiểm thử đơn vị tham số hóa và những kỹ thuật phức tạp đằng sau phương pháp kiểm thử mới này cũng như một số nghiên cứu liên quan. Qua đó khóa luận kết thúc bằng việc phác thảo một số hướng có thể phát triển tiếp để hệ thống này xử lý được các kiểu dữ liệu phức tạp hơn. ii MỤC LỤC LỜI CẢM ƠN i . i TÓM TẮT NỘI DUNG . ii MỤC LỤC iii CÁC KÝ HIỆU VIẾT TẮT iv DANH MỤC HÌNH VẼ v Chương 1: Kiểm thử đơn vị tham số hóa .3 1.1. Kiểm thử phần mềm .3 1.2. Kiểm thử đơn vị 4 1.3. Kiểm thử đơn vị tham số hóa .6 1.3.1. Khái niệm .6 1.3.2. Mối quan hệ giữa UT và PUT 7 1.3.3. Kiểm thử đơn vị tham số hóa với Pex .8 1.3.4. Các mẫu kiểm thử tham số hóa .9 1.3.5. Lựa chọn đầu vào kiểm thử với Pex 10 Chương 2: Sinh dữ liệu kiểm thử tự động cho PUT 12 2.1. Thực thi tượng trưng 13 2.1.1. Những khái niệm cơ bản 13 2.1.2. Thực thi tượng trưng tĩnh .14 2.1.3. Thực thi tượng trưng động 17 2.2. Xây dựng ràng buộc .22 2.2.1. Lưu trữ giá trị tượng trưng .24 2.2.2. SE với các kiểu dữ liệu nguyên thủy .25 2.2.3. SE với đối tượng 28 2.2.4. SE với các lời gọi phương thức .30 2.3. Sinh dữ liệu kiểm thử cho PUT 31 Chương 3: Sinh ca kiểm thử tham số hóa với JPF 36 3.1. Kiến trúc của JPF .36 3.2. Symbolic JPF 40 3.2.1. Bộ tạo chỉ thị 40 3.2.2. Các thuộc tính 41 3.2.3. Xử lý các điều kiện rẽ nhánh .42 3.2.4. Ví dụ .43 3.2.5. Kết hợp thực thi cụ thể và thực thi tượng trưng 47 3.3. Sinh PUT với Symbolic JPF .48 3.4. Mở rộng Symbolic JPF 53 3.4.1. Các phương pháp cũ .53 3.4.2. Hướng mở rộng .54 KẾT LUẬN . 58 TÀI LIỆU THAM KHẢO 1 iii CÁC KÝ HIỆU VIẾT TẮT CFG Control Flow Graph DSE Dynamic Symbolic Execution JPF Java PathFinder PC Path Condition PUT Parameterized Unit Test SE Symbolic Execution SET Symbolic Execution Tree TIS Test Input Selector UT Unit Test CFG Control Flow Graph DSE Dynamic Symbolic Execution JPF Java PathFinder PC Path Condition PUT Parameterized Unit Test SE Symbolic Execution SET Symbolic Execution Tree TIS Test Input Selector UT Unit Test iv DANH MỤC HÌNH VẼ Hình 1: Mối quan hệ giữa UT và PUT .8 Hình 2 : Cây thực thi tượng trưng 16 Hình 3: Cây thực thi tượng trưng được quản lý riêng 22 Hình 4 : Hệ thống kiểm thử tổng quát .24 Hình 5: Gán giá trị tượng trưng cho tham số đầu vào .26 Hình 6: Thực thi tượng trưng với câu lệnh gán .27 Hình 7: Thực thi tượng trưng với câu lệnh rẽ nhánh 27 Hình 8: Khởi tạo đối tượng làm đầu vào cho chương trình 29 Hình 9. Sinh ra các ràng buộc liên quan tới đối tượng .30 Hình 10: Thuật toán sinh dữ liễu kiểm thử 32 Hình 11: Các cây thực thi cục bộ tương ứng với hàm abs và TestAbs 34 Hình 12: Kiến trúc JPF 37 Hình 13: Bộ sinh lựa chọn trong JPF .39 Hình 14. Bộ tạo chỉ thị trong JPF 40 Hình 15. Trạng thái chương trình thực thi trong Symbolic JPF 41 Hình 16: Bùng nổ việc thực thi tượng trưng trong Symbolic JPF 48 Hình 17: Kiến trúc hệ thống cài đặt 49 Hình 18. Một ví dụ với hệ thống cài đặt .52 v MỞ ĐẦU Trong nền kinh tế hiện nay, ngành công nghiệp phần mềm giữ vai trò hết sức quan trọng. Với một số nước có nền công nghệ thông tin phát triển thì ngành công nghiệp phần mềm có khả năng chi phối cả nền kinh tế. Tuy nhiên để đảm bảo chất lượng cho các phần mềm là một thách thức không nhỏ trong ngành công nghiệp phần mềm. Việc phát hiện và khắc phục các lỗi cho các phần mềm là một công việc đòi hỏi nhiều nỗ lực và chi phí trong phát triển phần mềm. Với những lĩnh vực ứng dụng ngày càng mở rộng của phần mềm hiện nay thì chất lượng phần mềm càng được quan tâm hàng đầu. Trong kỹ nghệ phần mềm thì kiểm thử chính là phương pháp dùng để phát hiện các lỗi của phần mềm. Trong đó kiểm thử đơn vị là giai đoạn đầu tiên trong quy trình kiểm thử. Kiểm thử đơn vị là một công việc bắt buộc trong phát triển phần mềm. Theo nghiên cứu của Micorosoft thì có tới 79% các nhà phát triển phần mềm phải viết các ca kiểm thử đơn vị để thực hiện việc kiểm thử phần mềm mức đơn vị. Rõ ràng kiểm thử đơn vị là một công việc nặng nhọc làm mất nhiều thời gian và chi phí trong phát triển phần mềm. Do đó có một phương pháp kiểm thử đơn vị mới đã ra đời giúp cải thiện phương pháp kiểm thử đơn vị truyền thống đó là kiểm thử đơn vị tham số hóa. Với kiểm thử đơn vị tham số hóa công sức giành cho việc kiểm thử phần mềm mức đơn vị đã được giảm đi đáng kể. Kiểm thử đơn vị tham số hóa giúp việc phát hiện các lỗi của phần mềm đạt hiệu quả cao hơn do đó nâng cao chất lượng của phần mềm. Kiểm thử đơn vị tham số hóa còn là một phương pháp kiểm thử đơn vị còn rất mới và nó mới chỉ được áp dụng trong môi trường .NET. Vì vậy việc nghiên cứu về kiểm thử đơn vị tham số hóa và ứng dụng nó là một nhu cầu cấp bách. Và khóa luận này ra đời chính là vì mục đích này. Nội dụng chính của khóa luận gồm 3 chương: Chương 1: Trình bày tổng quan về kiểm thử và làm rõ bản chất của kiểm thử đơn vị tham số hóa thông qua công cụ Pex của Microsoft. Chương 2: Nghiên cứu về phương pháp sinh dữ liệu làm đầu vào kiểm thử cho các ca kiểm thử đơn vị tham số hóa. Trong chương này ta cũng sẽ trình bày về một hệ thống kiểm thử tổng quát nhất dùng để thực thi các ca kiểm thử đơn vị tham số hóa viết cho ngôn ngữ Java. 1 Chương 3: Trong chương này ta sẽ nghiên cứu về một nền (framework) kiểm chứng Java bytecode mã nguồn mở rất phổ biến hiện nay đó là Java PathFinder và áp dụng khả năng của nó để xây dựng một nền thực thi các ca kiểm thử tham số hóa viết cho những chương trình Java đơn giản. Đồng thời ta cũng đề xuất giải pháp để có thể mở rộng Java PathFinder cho mục đích hoàn thiện nền kiểm thử mà ta đã xây dựng. 2 Chương 1: Kiểm thử đơn vị tham số hóa 1.1. Kiểm thử phần mềm Để đảm bảo một hệ thống phần mềm hoặc các thành phần của phần mềm làm việc như mong muốn là một thách thức lớn trong ngành công nghiệp phần mềm. Các phần mềm lỗi gây ra những tổn thất về kinh tế cũng như những hậu quả nghiêm trọng khác tùy thuộc vào lĩnh vực mà phần mềm được sử dụng. Do đó cần phải phát hiện và khắc phục các lỗi của phần mềm trước khi đem chúng vào sử dụng. Có các phương pháp khác nhau để phát hiện lỗi của phần mềm bao gồm kiểm tra mô hình (model checking) [4], các kỹ thuật phân tích tĩnh (static analysis)[24] và kiểm thử (software testing)[1]. Các kỹ thuật phân tích chương trình tĩnh thường đưa ra nhiều cảnh báo (warnings) không tương ứng với các lỗi thực sự. Các kỹ thuật kiểm thử phát hiện ra các lỗi thực sự nhưng thường không phát hiện ra được tất cả các lỗi do chỉ phân tích một số sự thực thi trong chương trình. Trong kiểm tra mô hình, một mô hình của hệ thống được tạo ra để hỗ trợ phân tích mọi sự thực thi có thể trong mô hình. Kiểm tra mô hình có thể kiểm chứng được rằng mô hình của hệ thống hoạt động chính xác trong tất cả trường hợp có thể. Kiểm tra mô hình phân tích hết mọi khía cạnh thực thi của chương trình và chỉ ra những sự vi phạm nhưng không chứng minh được chương trình sẽ được thực thi chính xác mà không có lỗi. Hạn chế của kiểm tra mô hình đó là không gian trạng thái của mô hình thường quá lớn do đó việc thám hiểm tất cả các trạng thái không phải lúc nào cũng thực hiện được. Kiểm thử chính là kỹ thuật được sử dụng phổ biến nhất để phát hiện và khắc phục các lỗi của phần mềm nhằm đảm bảo chất lượng của phần mềm. Chi phí giành cho việc kiểm thử chiếm khoảng 50% tổng chi phí trong phát triển phần mềm. Kiểm thử là một tiến trình quan trọng trong kỹ nghệ phần mềm. Kiểm thử đơn vị chính là bước đầu tiên trong quy trình kiểm thử đó. Có các kỹ thuật kiểm thử khác nhau được sử dụng như kiểm thử hộp trắng (white-box testing), kiểm thử hộp đen (black-box testing), kiểm thử hộp xám (gray-box testing). Các kỹ thuật kiểm thử đó được dựa trên 2 loại kiểm thử đó là kiểm thử chức năng (funcional testing) và kiểm thử cấu trúc (structured testing). Kiểm thử chức năng là loại kiểm thử dựa trên đặc tả chức năng của hệ thống, nó phát hiện các sai sót về chức năng mà không quan tâm tới cài đặt. Kiểm thử cấu trúc là loại kiểm thử có nghiên cứu mã nguồn bằng việc phân tích thứ tự thực hiện các lệnh. 3 [...]... object()); } Với ca kiểm thử tham số hóa này phương thức Add của lớp ArrayList được kiểm thử với tất cả các trường hợp thực thi có thể xảy ra Thuộc tính [PexClass] của Pex để xác định một lớp kiểm thử là lớp chứa các ca kiểm thử tham số hóa Thuộc tính [PexMethod] để chỉ định một phương thức kiểm thử là ca kiểm thử tham số hóa Ta muốn viết một lớp kiểm thử chứa các ca kiểm thử tham số hóa cần sử dụng... số hóa cần sử dụng thuộc tính [PexClass] và [PexMethod] để viết các ca kiểm thử tham số hóa 1.3.4 Các mẫu kiểm thử tham số hóa Viết các ca kiểm thử tham số hóa là một nghệ thuật Để viết các ca kiểm thử tham số hóa hiệu quả, ta cần thực sự hiểu về mã cài đặt của chương trình mà ta muốn kiểm thử Pex hỗ trợ nhiều mẫu kiểm thử tham số hóa khác nhau[15] Các mẫu được sử dụng nhiều nhất đó là mẫu AAA (Triple-A)... cần được viết sao cho có thể sinh ra các UT tương ứng với các nền kiểm thử đó 7 Hình 1: Mối quan hệ giữa UT và PUT 1.3.3 Kiểm thử đơn vị tham số hóa với Pex Pex[30] là công cụ mạnh mẽ hỗ trợ việc viết và thực thi các ca kiểm thử tham số hóa cho môi trường NET Ví dụ 1.3: Ca kiểm thử tham số hóa sử dụng Pex : Cũng như với UT, ta có thể viết các lớp kiểm thử chứa các ca kiểm thử tham số hóa Với sự hỗ trợ... JUnit[33] cho Java, NUnit[34], VSUnit[29] cho NET để thực thi các ca kiểm thử đơn vị Tuy nhiên các nền kiểm thử này không hỗ trợ việc sinh tự động các ca kiểm thử đơn vị Việc viết các ca kiểm thử đơn vị để thực thi tất cả các đường đi của một chương trình là một công việc nặng nhọc Giải pháp để giảm công sức cho việc này đó là sử dụng ca kiểm thử đơn vị tham số hóa Kiểm thử đơn vị tham số hóa[ 7, 11,... pháp mới trong kiểm thử phần mềm Kiểm thử đơn vị tham số hóa giúp cải thiện nỗ lực trong việc phát triển phần mềm Về bản chất nó chính là sự mở rộng của phương pháp kiểm thử đơn vị truyền thống 1.3.1 Khái niệm Các UT truyền thống là các phương thức kiểm thử không tham số Ta có thể mở rộng các UT đó bằng cách cho phép truyền vào tham số cho các phương thức kiểm thử Các ca kiểm thử tham số hóa (PUT) là...1.2 Kiểm thử đơn vị Kiểm thử đơn vị là một cộng việc quan trọng trong kỹ nghệ phần mềm Kiểm thử đơn vị thường được áp dụng để kiểm tra việc cài đặt của các lớp hoặc phương thức Để thực hiện việc kiểm thử đơn vị, các lớp kiểm thử được tạo ra Các lớp kiểm thử này gồm các phương thức kiểm thử Các phương thức kiểm thử là các phương thức không tham số có kiểu trả về là void chứa trong các lớp kiểm thử để kiểm. .. kích cỡ miền giá trị của tham số đầu vào Các tham số đầu vào có giá trị thỏa mãn giả thuyết này mới được xem xét làm đầu vào kiểm thử Như với PUT ở trên thì chỉ các ArrayList khác null mới được lựa chọn làm đầu vào kiểm thử Khi Pex thực thi ca kiểm thử tham số hóa ở trên sẽ sinh ra Test Suite gồm 2 VSUnit UT Đồng thời Pex cũng báo cáo về kết quả xác nhận của ca kiểm thử tham số hóa ở trên [TestMethod]... hỗ trợ việc sinh tự động các ca kiểm thử một cách có hệ thống giúp giảm chi phí cho việc kiểm thử phần mềm Một trong những phương pháp đơn giản nhất để sinh tự động các ca kiểm thử đó là kiểm thử ngẫu nhiên (random testing)[5] Với kiểm thử ngẫu nhiên các đầu vào cho hệ thống được sinh ngẫu nhiên Để thực hiện, một luồng các bits được sinh ngẫu nhiên để thể hiện cho các giá trị của tham số đầu vào Giả... giá trị thực sự cho các tham số đầu vào để sinh lại các ca kiểm thử cụ thể PUT sẽ không thể thực thi nếu không có các giá trị cụ thể được truyền vào cho các tham số đầu vào của PUT Để có thể sinh các đầu vào cụ thể cho PUT Pex cần phải phân tích chương trình mà PUT kiểm thử Có 2 kỹ thuật phân tích chương trình đó là phân tích tĩnh và phân tích động: + Phân tích tĩnh (static analysis): Kiểm chứng một... của chương trình Mỗi phương thức kiểm thử trong các lớp kiểm thử biểu thị cho một ca kiểm thử đơn vị (UT) Có thể chia một phương thức kiểm thử ra làm 3 phần: Các giá trị đầu vào, dãy các lời gọi phương thức, và sự xác nhận (assertions) Kiểm thử thất bại nếu bất cứ sự xác nhận nào bị vị phạm hoặc có một ngoại lệ (exception) xảy ra Ví dụ 1.1: Ta xét một phương thức kiểm thử được viết trong nền kiểm thử . đ nh m t lớp ki m th là lớp ch a các ca ki m th tham s h a. Thuộc t nh [PexMethod] để ch đ nh m t phư ng th c ki m th là ca ki m th tham s h a. Ta. đ ng ch nh xác trong tất cả tr ng h p có th . Ki m tra m h nh phân t ch h t m i kh a c nh th c thi c a ch ng tr nh và ch ra nh ng s vi ph m nh ng không