Chương 2: Phương pháp sinh dữ liệu kiểm thử dòng điều khiển Chương này trình bày tổng quan về phương pháp kiểm thử dòng điều khiển từ đồ thị dòng điều khiển Control Flow Graph - CFG của
Trang 1ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ
Trang 2ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ
Mã số: 848 01 03.01
LUẬN VĂN THẠC SĨ Ngành: Kỹ Thuật Phần Mềm
NGƯỜI HƯỚNG DẪN KHOA HỌC: PGS TS Phạm Ngọc Hùng
HÀ NỘI – 2019
Trang 3VIETNAM NATIONAL UNIVERSITY, HANOI UNIVERSITY OF ENGINEERING AND TECHNOLOGY
NGUYEN THI KHANH CHI
A METHOD FOR AUTOMATED TEST DATA GENERATION FROM SOURCE CODE AND APPLICATION IN BUILDING PROGRAMMING
MARKING SYSTEM
THE MS THESIS Major: InformationTechnology
Supervisor: Assoc Prof Pham Ngoc Hung
HANOI - 2019
Trang 4MỤC LỤC
MỤC LỤC i
LỜI CẢM ƠN iii
TÓM TẮT iv
ABSTRACT v
LỜI CAM ĐOAN vi
DANH MỤC THUẬT NGỮ VIẾT TẮT vii
DANH MỤC HÌNH VẼ viii
DANH MỤC BẢNG x
Chương 1: Mở đầu 1
Chương 2: Phương pháp sinh dữ liệu kiểm thử dòng điều khiển 3
2.1Tổng quan về kiểm thử dòng điều khiển 3
2.2Các tiêu chí kiểm thử 4
2.3Xây dựng đồ thị dòng điều khiển 6
2.3.1.Xây dựng đồ thị dòng điều khiển ứng với tiêu chí phủ câu lệnh và phủ nhánh 8
2.3.2 Xây dựng CFG ứng với tiêu chí phủ điều kiện con 9
2.3.3 Phương pháp xây dựng CFG từ mã nguồn Java 10
2.4 Sinh đường đi kiểm thử từ đồ thị 12
2.4.1 Sinh đường đi thỏa mãn tiêu chí phủ câu lệnh 12
2.4.2 Sinh đường đi thỏa mãn tiêu chí phủ nhánh 13
2.4.3 Sinh đường đi thỏa mãn tiêu chí phủ điều kiện con 13
2.4.4 Phương pháp sinh đường đi kiểm thử trên đồ thị 14
2.5 Sinh ca kiểm thử từ đường đi 15
2.5.1 Sinh dữ liệu kiểm thử 15
2.5.2 Sinh đầu ra mong muốn 17
2.6 Sinh các ca kiểm thử giá trị biên và vòng lặp 17
2.6.1.Sinh ca kiểm thử giá trị biên 18
2.6.2 Sinh ca kiểm thử vòng lặp 19
Chương 3: Công cụ và thực nghiệm 22
Trang 53.1Đặc tả hệ thống chấm bài lập trình 22
3.1.1 Danh sách các tác nhân 22
3.1.2 Mô tả các ca sử dụng của hệ thống: 24
3.2 Kiến trúc tổng thể của hệ thống chấm bài lập trình 27
3.3Kiến trúc của mô-đun sinh ca kiểm thử tự động 28
3.4Giới thiệu công cụ sinh ca kiểm thử tự động 29
3.3.1.Giao diện công cụ sinh ca kiểm thử tự động 29
3.3.2.Đồ thị dòng điều khiển 29
3.3.3.Tập các đường kiểm thử 31
3.3.4 Tập các ca kiểm thử 31
3.5Kết quả thực nghiệm 33
Bài toán 1: Bài toán kiểm tra năm nhuận 33
Bài toán 2: Bài toán tính số ngày trong một tháng 35
Bài toán 3: Tìm ước số chung lớn nhất 40
3.6 Ý nghĩa của thực nghiệm 44
Chương 4: Kết luận 46
TÀI LIỆU THAM KHẢO 47
Trang 6LỜI CẢM ƠN
Trước tiên, tôi xin gửi lời cảm ơn chân thành và sâu sắc đến người thầy đáng kính PGS TS Phạm Ngọc Hùng - người đã trực tiếp hướng dẫn, chỉ bảo và giúp đỡ tôi trong suốt quá trình tôi học tập và nghiên cứu tại trường Nhờ có lòng tốt của thầy,
sự say mê nghiên cứu khoa học, kiến thức uyên thâm và sự hướng dẫn tận tình, tôi đã vượt qua được những khó khăn từ phía gia đình để tiếp tục học tập, nghiên cứu và hoàn thiện luận văn này
Tôi xin chân thành cảm ơn các thầy cô giáo khoa Công nghệ thông tin, trường Đại học Công nghệ, Đại học Quốc Gia Hà Nội đã nhiệt tình giảng dạy, truyền đạt những kiến thức quý báu trong suốt quá trình tôi học tập và nghiên cứu tại trường Tôi xin chân thành cảm ơn những người thân trong gia đình, các bạn bè, đồng nghiệp luôn tạo điều kiện, giúp đỡ động viên tôi trong công tác nghiên cứu khoa học Cuối cùng, tôi xin cảm ơn ban giám hiệu trường THPT Ngô Gia Tự - Từ Sơn - Bắc Ninh nơi tôi công tác, các đồng nghiệp và các em học sinh khối 11 đã tạo điều kiện tối đa, đóng góp những nhận xét khách quan cho đề tài nghiên cứu để tôi có thể hoàn thành luận văn Thạc sỹ tại trường Đại học Công nghệ - Đại học Quốc Gia Hà Nội
Trang 7TÓM TẮT
Luận văn tập trung nghiên cứu phương pháp sinh các ca kiểm thử từ mã nguồn
và ứng dụng trong việc tự động chấm các bài tập lập trình của học sinh viết bằng ngôn ngữ Java nhằm hỗ trợ các giáo viên Tin học tại các Trường Trung học phổ thông/Trung học cơ sở trong việc sinh các ca kiểm thử và chấm các bài tập lập trình của học sinh Với mỗi bài tập, giáo viên sẽ cung cấp mã nguồn mẫu (mã nguồn không
có lỗi) Dựa vào mã nguồn này, chúng ta sẽ tiến hành phân tích nhằm xây dựng đồ thị dòng điều khiển của mã nguồn Tiếp đến, các đường đi của đồ thị ứng với các dòng điều khiển có thể có của chương trình sẽ được sinh Từ các đường đi này, chúng ta sẽ xây dựng hệ ràng buộc chứa các điều kiện của các tham số Việc sinh dữ liệu kiểm thử trên đường thực thi chính là việc giải hệ ràng buộc trên đường đi tương ứng Khi có dữ liệu kiểm thử, chúng ta sẽ sử dụng đầu ra của mã nguồn chuẩn để sinh giá trị đầu ra mong muốn tương ứng Cùng với các ca kiểm thử đã được sinh ra, luận văn còn nghiên cứu các giải pháp để sinh các ca kiểm thử cho các vòng lặp và sinh các ca kiểm thử tại các biên của từng tham số ứng với miền giá trị và đặc tả của bài toán
Luận văn cũng đã tiến hành xây dựng công cụ hỗ trợ và áp dụng thử nghiệm với các chương trình đơn giản nhằm minh chứng cho tính đúng đắn và tính hiệu quả của phương pháp đề xuất Tuy nhiên, công cụ cài đặt chưa được hoàn thiện và cần được tiếp tục phát triển nhằm có một công cụ hỗ trợ giáo viên như đã nêu ở trên
Từ khóa: Kiểm thử tự động, sinh dữ liệu kiểm thử, độ phủ kiểm thử, kiểm thử hộp
trắng
Trang 8ABSTRACT
The thesis focuses on studying the method of testing data from source code and applying in automatically marking students' programming exercises written in Java language to support Informatics teachers at high schools information / junior high school in testing test cases and marking students' programming exercises For each teacher exercise, the teacher will provide sample source code (source code without errors) Based on this source code, we will conduct source code analysis to build control line graph of source code Next, we will generate the graph's paths corresponding to the possible control lines of the program From these paths, we will build the binding system without the conditions of the parameters Generating test data corresponding to the corresponding path is the finding of a solution of the corresponding system of equations Whenever there is test data, we will use the specification to generate the desired output values Along with the test cases as born, the thesis also studies solutions to generate test cases for loops and generate test cases
at the boundaries of each parameter corresponding to the value domain and specification of the problem
The thesis has also developed support tools and applied experiments with simple programs to demonstrate the correctness and effectiveness of the proposed method However, the installation tool has not been completed and needs to be further developed in order to have a teacher support tool as mentioned above
Keywords: Automated testing, test data generation, test coverage, white-box
testing
Trang 9LỜI CAM ĐOAN
Tôi xin cam đoan luận văn Thạc sỹ Công nghệ thông tin "Phương pháp sinh dữ liệu kiểm thử từ mã nguồn và ứng dụng xây dựng hệ thống chấm bài tập lập trình" là công trình nghiên cứu của tôi dưới sự hướng dẫn của Thầy hướng dẫn, không sao chép lại của người khác Trong toàn bộ nội dung luận văn, những điều được trình bày là của
cá nhân tôi hoặc là được tổng hợp từ các nguồn tài liệu khác Tất cả các nguồn tài liệu tham khảo đều có trích dẫn cụ thể và hợp pháp
Tôi xin hoàn toàn chịu trách nhiệm và chịu mọi hình thức kỷ luật theo quy định của trường Đại học Công Nghệ - Đại học Quốc Gia Hà Nội cho lời cam đoan này
Hà Nội, ngày 26 tháng 03 năm 2019
Nguyễn Thị Khánh Chi
Trang 10DANH MỤC THUẬT NGỮ VIẾT TẮT
7 SMT-Solver Satisfiability Modulo Theories
Solver
Trang 11DANH MỤC HÌNH VẼ
Hình 2.1 Tổng quan quy trình kiểm thử dòng điều khiển 3
Hình 2.2 Mã nguồn hàm laNamNhuan 5
Hình 2.3 Các thành phần cơ bản của đồ thị dòng điều khiển 7
Hình 2.4 Các cấu trúc điều khiển cơ bản của đồ thị dòng điều khiển 7
Hình 2.5 Mã nguồn và CFG ứng với tiêu chí phủ câu lệnh hàm laNamNhuan 8
Hình 2.6 Mã nguồn và CFG ứng với tiêu chí phủ điều kiện con hàm laNamNhuan 9
Hình 2.7 Mã nguồn và CFG ứng với tiêu chí phủ câu lệnh hàm laNamNhuan 13
Hình 2.8 Mã nguồn và CFG ứng với tiêu chí phủ điều kiện con hàm laNamNhuan 14
Hình 2.9 Mã nguồn và CFG ứng với tiêu chí phủ nhánh hàm giaithua 20
Hình 3.1 Biểu đồ ca sử dụng của hệ thống chấm bài lập trình 23
Hình 3.2 Kiến trúc tổng thể của hệ thống chấm bài lập trình 27
Hình 3.3 Kiến trúc của mô-đun sinh ca kiểm thử tự động 28
Hình 3.4 Giao diện của công cụ sinh ca kiểm thử tự động 29
Hình 3.5 CFG ứng với tiêu chí phủ câu lệnh và phủ nhánh hàm laNamNhuan 30
Hình 3.6 CFG ứng với tiêu chí phủ điều kiện con hàm laNamNhuan 30
Hình 3.7 Chi tiết các đường kiểm thử cho tiêu chí phủ nhánh hàm laNamNhuan 31
Hình 3.8 Chi tiết các ca kiểm thử cho tiêu chí phủ câu lệnh của hàm laNamNhuan 32
Hình 3.9 Kết quả kiểm thử được xuất dưới dạng MS Excel hàm laNamNhuan 32
Hình 3.10 Mã nguồn chuẩn của hàm laNamNhuan 33
Hình 3.11 Chi tiết ca kiểm thử cho tiêu chí phủ điều kiện con ham laNamNhuan 33
Hình 3.12 Mã nguồn hàm laNamNhuan1 của học sinh thứ nhất 34
Hình 3.13 Mã nguồn hàm laNamNhuan2 của học sinh thứ hai 34
Hình 3.14 Mã nguồn chuẩn của hàm songay 36
Hình 3.15 Chi tiết ca kiểm thử cho tiêu chí phủ điều kiện con hàm songay 36
Hình 3.16 Mã nguồn hàm songayhs_1 của học sinh thứ nhất 37
Hình 3.17 Mã nguồn hàm songayhs_2 của học sinh thứ hai 37
Hình 3.18 Mã nguồn chuẩn của hàm timuscln 40
Hình 3.19 Chi tiết các ca kiểm thử cho tiêu chí phủ nhánh hàm timuscln 40
Trang 12Hình 3.20 Chi tiết các ca kiểm thử phủ tất cả các nhánh hàm timuscln 41 Hình 3.21 Mã nguồn hàm timuscnl_1 của học sinh thứ nhất 41 Hình 3.22 Mã nguồn hàm timuscln_2 của học sinh thứ hai 41
Trang 13DANH MỤC BẢNG
Bảng 2.1 Các ca kiểm thử cho tiêu chí phủ câu lệnh của hàm laNamNhuan 5
Bảng 2.2 Các trường hợp cần kiểm thử với tiêu chí phủ nhánh cho hàm laNamNhuan 5 Bảng 2.3 Các trường hợp cần kiểm thử với tiêu chí phủ điều kiện con của hàm laNamNhuan 6
Bảng 2.4 Các ca kiểm thử cho tiêu chí phủ điều kiện con hàm laNamNhuan 6
Bảng 2.5 Dữ liệu kiểm thử cho tiêu chí phủ điều kiện con hàm laNamNhuan 16
Bảng 2.6 Các ca kiểm thử cho tiêu chí phủ câu lệnh hàm laNamNhuan 17
Bảng 2.7 Các ca kiểm thử giá trị biên cho hàm laNamNhuan 18
Bảng 2.8 Các ca kiểm thử cho tiêu chí phủ nhánh hàm giaithua 20
Bảng 2.9 Các ca kiểm thử vòng lặp for hàm giaithua 21
Bảng 3.1 Danh sách tác nhân của hệ thống chấm bài lập trình 22
Bảng 3.2 Danh sách các ca sử dụng của hệ thống chấm bài lập trình 23
Bảng 3.3 Kết quả kiểm thử bài tập kiểm tra năm nhuận của hai học sinh 34
Bảng 3.4 Các ca kiểm thử giá trị biên cho hàm laNamNhuan 35
Bảng 3.5 Kết quả kiểm thử giá trị biên bài tập kiểm tra năm nhuận của hai học sinh 35 Bảng 3.6 Kết quả kiểm thử bài tập tính số ngày trong tháng của hai học sinh 38
Bảng 3.7 Các ca kiểm thử giá trị biên cho hàm songay 39
Bảng 3.8 Kết quả kiểm thử giá trị biên bài tập tính số ngày trong tháng của hai học sinh 39
Bảng 3.9 Kết quả kiểm thử bài tập tìm ước số chung lớn nhất của hai học sinh 42
Bảng 3.10 Các ca kiểm thử giá trị biên cho hàm timuscln 43
Bảng 3.11 Kết quả kiểm thử giá trị biên bài tập tìm uscln của hai của học sinh 43
Bảng 3.12 Các ca kiểm thử vòng lặp while cho hàm timuscln 44
Bảng 3.13 Kết quả kiểm thử vòng lặp while cho hàm tìm uscln của hai học sinh 44
Trang 14Chương 1: Mở đầu
Hiện nay, môn học lập trình đã được đưa vào giảng dạy ở các trường Trung học phổ thông (THPT) trên toàn quốc, giúp các em học sinh làm quen với công việc lập trình và làm quen dần với tư duy thiết kế các thuật toán Ngôn ngữ lập trình được sử dụng để giảng dạy trong hầu hết các trường THPT là Pascal Tuy nhiên, theo chương trình giáo dục THPT mới, trên cơ sở định hướng lập trình và tùy chọn ngôn ngữ, nhiều trường THPT đã bước đầu đưa các ngôn ngữ lập trình phổ biến như C, Java, v.v vào giảng dạy Trong quá trình giảng dạy, công việc chấm bài tập lập trình đối với người giáo viên thường diễn ra thủ công và tiềm ẩn nhiều sai sót Do thời gian chấm bài có hạn nên việc không phát hiện ra các lỗi trong bài lập trình là không tránh khỏi Điều này dẫn đến điểm chấm chưa thực sự chính xác và công bằng Làm thế nào để công việc chấp bài lập trình được dễ dàng hơn với các giáo viên, cũng như đảm bảo tính chính xác, rút ngắn thời gian chấm bài là mục tiêu cần hướng tới
Đối với các bài tập lập trình, việc chấm bài chính là rà soát để phát hiện các lỗi
có thể có trên mã nguồn của bài tập học sinh Khi chương trình xuất hiện lỗi cú pháp, các lỗi sẽ được trình biên dịch phát hiện để người lập trình sửa lỗi Tuy nhiên, ngay cả khi một chương trình không có lỗi cú pháp thì chương trình vẫn chưa chắc đã đúng vì lỗi có thể xảy ra trong quá trình thiết kế giải thuật Làm thế nào để hỗ trợ giáo viên kiểm tra xem chương trình có thực hiện đúng với đặc tả yêu cầu của bài toán hay không, hoặc đúng bao nhiêu phần so với đặc tả của bài toán chính là mục tiêu của quá trình chấm bài Hơn nữa, việc giáo viên cung cấp các cơ chế cho phép học sinh tự làm bài và tương tác qua các ứng dụng nhằm nâng cao khả năng tự học và tăng cường chất lượng là một xu hướng tất yếu trong hệ thống giáo dục thời gian tới Vì vậy, nhu cầu
về bài toán này càng cấp thiết hơn
Để giải quyết vấn đề này, ứng với mỗi bài toán, giáo viên phải sinh ra một bộ ca kiểm thử đủ tốt (có khả năng phát hiện tất cả các lỗi có thể có của bài lập trình của học sinh) Bộ ca kiểm thử này sau đó sẽ được sử dụng để chấm các chương trình cho học sinh nộp (tự động hoặc thủ công tùy thuộc vào phương pháp và công cụ mà giáo viên
sử dụng) Hiện tại, việc sinh ra các bộ ca kiểm thử như vậy là vượt ngoài khả năng của các giáo viên Trung học phổ thông Vì vậy, có một công cụ tự động hỗ trợ giáo viên giải quyết bài toán này là một vấn đề cấp thiết, có ý nghĩa thực tiễn cao Một trong những giải pháp để giải quyết vấn đề này là sinh dữ liệu kiểm thử từ mã nguồn sử dụng phương pháp kiểm thử dòng dữ liệu [2, 3, 4, 8, 9, 11] Trong phương pháp này, ứng với đặc tả của mỗi bài toán, thay vì yêu cầu giáo viên phải sinh bộ ca kiểm thử,
họ sẽ phải cung cấp mã nguồn mẫu (mã nguồn của bài toán tương ứng mà không có lỗi) Phương pháp này sẽ tự động sinh các ca kiểm thử (bao gồm dữ liệu kiểm thử và giá trị đầu ra mong muốn tương ứng) từ mã nguồn được giáo viên cung cấp Sau khi
Trang 15hoàn tất quá trình này, giáo viên sẽ có một bộ dữ liệu kiểm thử bao quát hết các nhánh của mã nguồn Tuy nhiên, phương pháp này [2, 3] chỉ cho phép phát hiện những lỗi tiềm ẩn trong mã nguồn (có đặc tả và được lập trình hoặc không có đặc tả và được lập trình) Phương pháp này không kiểm tra được các lỗi ứng với tình huống có đặc tả và không được lập trình (thường được phát hiện bởi các phương pháp kiểm thử hộp đen) Phương pháp đề xuất trong [2] mới sinh được các dữ liệu kiểm thử, chưa sinh được đầu ra mong muốn, do đó không hỗ trợ được giáo viên trong việc sinh các ca kiểm thử mẫu Trong [3] đã sinh được các ca kiểm thử cho mã nguồn Java nhưng chưa hỗ trợ xây dựng hệ thống chấm bài
Mục tiêu của luận văn này là hướng đến nghiên cứu giải pháp và xây dựng bộ công cụ hỗ trợ giáo viên chấm bài lập trình một cách tự động nhằm giải quyết các vấn
đề như mô tả ở trên Mấu chốt của giải pháp này là phương pháp sinh dữ liệu kiểm thử
từ mã nguồn Bản chất của các phương pháp này là phụ thuộc vào ngôn ngữ lập trình được sử dụng (mỗi ngôn ngữ lập trình thường có kỹ thuật sinh dữ liệu kiểm thử khác nhau vì chúng ta cần phải phân tích mã nguồn) Mặc dù ngôn ngữ lập trình được dùng phổ biến nhất trong các trường Trung học phổ thông là Pascal nhưng ngôn ngữ này chưa có công cụ phân tích cây cú pháp (nền tảng cho việc xây dựng đồ thị dòng điều khiển) Vì vậy, phương pháp sinh dữ liệu kiểm thử từ mã nguồn Pascal rất khó thực hiện trong luận văn này Ngôn ngữ C/C++ đã được quan tâm nghiên cứu với giải pháp khá tốt trong [2] Vì vậy, luận văn này tập trung nghiên cứu giải pháp cho ngôn ngữ Java Trong [3] đã nghiên cứu giải pháp tương tự cho Java nhưng chỉ dừng lại với các đơn vị chương trình (hàm, phương thức) Phương pháp này có thể sử dụng khi chương trình được viết bằng phương pháp hướng đối tượng Tuy nhiên, học sinh tại các trường Trung học phổ thông thường viết chương trình theo phương pháp hướng cấu trúc nên giải pháp này không sử dụng được Cùng với phương pháp này, luận văn cũng sẽ nghiên cứu các kỹ thuật kiểm thử hộp đen nhằm sinh bổ sung các ca kiểm thử cho phương pháp trên Một công cụ hỗ trợ cũng sẽ được phát triển và thực nghiệm với một
số chương trình đơn giản ở bậc Trung học phổ thông nhằm minh chứng cho kết quả của luận văn
Phần còn lại của đề tài nghiên cứu sẽ gồm những nội dung sau Chương 2 trình bày tổng quan phương pháp sinh dữ liệu kiểm thử dòng điều khiển từ mã nguồn Đây
là phương pháp chung, có thể áp dụng cho nhiều ngôn ngữ lập trình khác nhau, trong chương này cũng đề xuất phương pháp phân tích mã nguồn Java nhằm sinh ca kiểm thử cho các hàm Java Chương 3 giới thiệu công cụ hỗ trợ sinh ca kiểm thử tự động và kết quả thực nghiệm bằng cách áp dụng công cụ, cài đặt với một số chương trình đơn giản Cuối cùng, kết luận và các hướng nghiên cứu của luận văn sẽ được mô tả trong Chương 4
Trang 16Chương 2: Phương pháp sinh dữ liệu kiểm thử dòng điều khiển
Chương này trình bày tổng quan về phương pháp kiểm thử dòng điều khiển từ đồ thị dòng điều khiển (Control Flow Graph - CFG) của chương trình nhằm sinh ca kiểm thử cho mã nguồn ứng với tiêu chí kiểm thử yêu cầu Phương pháp trình bày trong chương này có thể áp dụng cho hầu hết các ngôn ngữ lập trình
2.1 Tổng quan về kiểm thử dòng điều khiển
Kiểm thử dòng điều khiển là phương pháp kiểm thử hộp trắng nhằm phát hiện các lỗi tiềm ẩn xảy ra trên mã nguồn [1, 6] Phương pháp này dựa vào việc phân tích
mã nguồn nhằm xây dựng đồ thị dòng điều khiển ứng với các tiêu chí kiểm thử cho trước Dựa vào đồ thị này, một bộ dữ liệu kiểm thử sẽ được sinh ra đáp ứng 100% tiêu chí kiểm thử yêu cầu Người sử dụng sẽ sử dụng đặc tả của bài toán để sinh ra các ca kiểm thử từ bộ dữ liệu kiểm thử đã được sinh ra Bộ ca kiểm thử này sau đó sẽ được sử dụng để làm bộ kiểm thử mẫu thực hiện kiểm thử trên bài tập lập trình của học sinh phục vụ cho quá trình chấm bài
Hình 2.1 Tổng quan quy trình kiểm thử dòng điều khiển
Xây dựng CFG
Sinh đường đi kiểm thử
Sinh dữ liệu kiểm thử
Sinh đầu ra mong muốn
Trang 17Quy trình kiểm thử dòng điều khiển của một hàm được mô tả như Hình 2.1 Đầu vào của quy trình là mã nguồn và tiêu chí kiểm thử yêu cầu Đầu ra của quy trình là báo cáo kiểm thử chứa các kết quả kiểm thử (ca kiểm thử nào phát hiện được lỗi và ca kiểm thử nào không phát hiện được lỗi) Chi tiết phương pháp bao gồm các bước sau:
- Bước 1: Sinh đồ thị dòng điều khiển Mã nguồn được phân tích dựa trên các tiêu chí
kiểm thử để xây dựng đồ thị dòng điều khiển Với mỗi tiêu chí kiểm thử là phủ câu lệnh, phủ nhánh và phủ điều kiện con, sẽ có một đồ thị dòng điều khiển tương ứng
- Bước 2: Sinh các đường đi kiểm thử Từ đồ thị dòng điều khiển, luận văn đề xuất
thuật toán duyệt đồ thị sao cho các đường đi kiểm thử được sinh ra đạt độ phủ thỏa mãn các tiêu chí đã đề ra
- Bước 3: Sinh ca kiểm thử Ca kiểm thử bao gồm bộ giá trị đầu vào được chọn để
thực hiện kiểm thử trên mỗi đường đi và giá trị đầu ra mong muốn tương ứng (Expected Output – EO) Ca kiểm thử được sinh ra bằng cách các hệ ràng buộc trên mỗi đường kiểm thử Giá trị đầu ra mong muốn được sinh từ đặc tả bài toán Kết thúc bước này, một tập các ca kiểm thử được sinh ra
- Bước 4: Thực thi các ca kiểm thử Thực thi các ca kiểm thử nhằm tạo ra báo cáo
kiểm thử trong đó chỉ ra ca kiểm thử nào phát hiện được lỗi, ca kiểm thử nào không phát hiện được lỗi
2.2 Các tiêu chí kiểm thử
Tiêu chí kiểm thử là chuẩn mực để đánh giá độ bao phủ của một tập ca kiểm thử
so với mã nguồn Nhằm tối ưu các ca kiểm thử, tiêu chí kiểm thử được đưa ra để thiết
kế các ca kiểm thử sao cho số ca kiểm thử là ít nhất những vẫn có thể kiểm tra được tối
đa các trường hợp (có thể mắc lỗi) xảy ra trên mã nguồn Các thành phần cần kiểm tra bao gồm câu lệnh, các đỉnh quyết định, các điều kiện con, đường thi thành hoặc sự kết hợp giữa chúng [1]
Có rất nhiều tiêu chí kiểm thử được áp dụng trong thực tế, dưới đây là ba tiêu chí kiếm thử đang được sử dụng rộng rãi [1, 2]:
- Phủ câu lệnh: Sau khi thực hiện các ca kiểm thử, mỗi dòng lệnh trên mã nguồn
phải được duyệt qua ít nhất một lần Giả sử, ta cần sinh các ca kiểm thử cho hàm
laNamNhuan có mã nguồn được hiển thị ở Hình 2.2 Để đạt được 100% tiêu chí
phủ câu lệnh cho hàm, ta cần thực hiện ba ca kiểm thử như Bảng 2.1 Giá trị EO (Expected Output) trên bảng là giá trị đầu ra mong muốn khi chạy ca kiểm thử,
RO (Real Output) là giá trị đầu ra thực tế (giá trị này sẽ được điền khi chạy các ca kiểm thử trong môi trường thực)
Trang 18Hình 2.2 Mã nguồn hàm laNamNhuan
Bảng 2.1 Các ca kiểm thử cho tiêu chí phủ câu lệnh của hàm laNamNhuan
- Phủ nhánh: Sau khi thực hiện ca kiểm thử, các điểm quyết định trên mã nguồn
được duyệt theo cả hai nhánh đúng và sai Ví dụ, với hàm laNamNhuan, để đạt
được 100% tiêu chí phủ nhánh, ta cần thực hiện các ca kiểm thử để kiểm tra các điều kiện như Bảng 2.2 để các điểm quyết định ở câu lệnh 1 và câu lệnh 3 được duyệt qua cả hai nhánh đúng và sai
Bảng 2.2 Các trường hợp cần kiểm thử với tiêu chí phủ nhánh cho hàm laNamNhuan
Hàm laNamNhuan là một trường hợp đặc biệt, ba ca kiểm thử thỏa mãn tiêu chí
phủ câu lệnh cũng đồng thời thỏa mãn tiêu chí phủ nhánh Trong nhiều trường hợp khác, số ca kiểm thử ứng với tiêu chí phủ nhánh thường nhiều hơn số ca kiểm thử của tiêu chí phủ câu lệnh do các ca kiểm thử của tiêu chí phủ câu lệnh không phủ được hết các nhánh đúng và sai trên mã nguồn
- Phủ điều kiện con: Với các điểm quyết định có chứa điều kiện phức hợp (từ hai
điều kiện con trở lên), sau khi thực hiện các ca kiểm thử, tất cả các điều kiện con đều được duyệt qua cả hai nhánh đúng và sai Ví dụ, trong câu lệnh 3 của hàm
laNamNhuan có chứa điều kiện phức hợp là (year%400==0)|| ((year%4==0)&&(year%100!=0)) Nếu chỉ thực hiện kiểm thử với tiêu chí phủ
Trang 19nhánh thì chỉ có điều kiện (year%400==0)được kiểm tra, còn hai điều kiện con
(year%4==0) và (year%100!=0) thì chưa được kiểm tra tới Chúng ta cần phải kiểm tra tất cả các nhánh trên các điều kiện trên mã nguồn thì mới đạt được tiêu chí phủ điều kiện con Bảng 2.3 là các trường hợp cần kiểm tra để mọi điều kiện
con trên hàm laNamNhuan đều được "ghé thăm".
Bảng 2.3 Các trường hợp cần kiểm thử với tiêu chí phủ điều kiện con của hàm
Bảng 2.4 Các ca kiểm thử cho tiêu chí phủ điều kiện con của hàm laNamNhuan
2.3 Xây dựng đồ thị dòng điều khiển
Đồ thị dòng điều khiển (CFG) là một phần rất quan trọng trong phương pháp kiểm thử dòng điều khiển CFG mô tả cấu trúc của mã nguồn thông qua một đồ thị có hướng với mỗi đỉnh tương ứng là một câu lệnh/nhóm lệnh CFG cho người dùng quan sát một cách trực quan các luồng điều khiển của mã nguồn Từ đó, chúng ta dễ dàng thiết kế các ca kiểm thử sao cho nó phủ hết các nhánh trên đồ thị này
Để xây dựng được CFG từ mã nguồn, ta quy ước mỗi câu lệnh/ nhóm lệnh trên
mã nguồn tương ứng là một đỉnh của đồ thị Nếu một câu lệnh j thực hiện ngay sau câu
Trang 20lệnh i thì sẽ tồn tại một đường đi từ đỉnh i đến đỉnh j Mỗi tiêu chí kiểm thử, chúng ta
xây dựng được một CFG tương ứng [1]
Một CFG được xây dựng từ đỉnh bắt đầu (ứng lời khai báo hàm), đi qua các đỉnh
(các câu lệnh khai báo, câu lệnh gán, câu lệnh điều kiện, câu lệnh lặp, các khối xử lý )
theo thứ tự thực hiện trên mã nguồn và đi đến đỉnh kết thúc (ứng với điểm kết thúc
hàm) Các thành phần để xây dựng CFG được mô tả ở Hình 2.3 [1]
Hình 2.3 Các thành phần cơ bản của đồ thị dòng điều khiển
Ngoài đỉnh bắt đầu và đỉnh kết thúc, mỗi đỉnh là duy nhất trong đồ thị, các đỉnh
khác trong đồ thị tương ứng với một câu lệnh của mã nguồn, được đặt tên theo chức
năng của câu lệnh Đỉnh xử lý ứng với câu lệnh khai báo, gán giá trị hoặc các câu lệnh tính toán Đỉnh quyết định ứng với câu lệnh rẽ nhánh hoặc biểu thức điều kiện trong câu lệnh lặp Đỉnh nối là đỉnh tiếp theo được thực hiện ngay sau khi câu lệnh rẽ nhánh
hoặc lặp kết thúc [1, 2, 6]
Trong Java, các cấu trúc điều khiển bao gồm: cấu trúc tuần tự, cấu trúc rẽ nhánh
if…else, cấu trúc rẽ nhánh switch case, các cấu trúc lặp while do, do while Riêng
vòng lặp for, chúng ta sử dụng cấu trúc while do để thay thế (vì for là một trường hợp đặc biệt của while do với số lần lặp biết trước) Các ký hiệu đại diện cho mỗi cấu trúc
điều khiển được minh họa trên Hình 2.4 [1, 2] Chúng ta sẽ sử dụng các thành phần và cấu trúc ở Hình 2.3, Hình 2.4 cùng với các tiêu chí kiểm thử để xây dựng đồ thị dòng điều khiển cho mã nguồn
Hình 2.4 Các cấu trúc điều khiển cơ bản của đồ thị dòng điều khiển
lý
Đỉnh quyết định
Đỉnh nối
Đỉnh kết thúc
Cấu trúc while do
Cấu trúc do while
Cấu trúc switch…case
Trang 212.3.1 Xây dựng đồ thị dòng điều khiển ứng với tiêu chí phủ câu lệnh và phủ nhánh
Chúng ta sẽ thực hiện xây dựng CFG từ mã nguồn theo các bước như sau: Đầu
tiên, ta đánh số thứ tự cho các câu lệnh trên mã nguồn Từ đỉnh bắt đầu ứng với lời gọi
hàm ta lần lượt nối các đỉnh theo thứ tự thực hiện câu lệnh trên mã nguồn [1, 2] Do tiêu chí phủ câu lệnh và phủ nhánh có các đường đi phủ toàn bộ các câu lệnh trên mã nguồn, nên CFG của hai tiêu chí này có hình dạng giống nhau CFG của tiêu chí phủ điều kiện con có cấu trúc phức tạp hơn do các đường đi trên đồ thị này phủ đến cả hai nhánh của các điều kiện con cơ bản
Hình 2.5 Mã nguồn và CFG ứng với tiêu chí phủ câu lệnh của hàm laNamNhuan
Giả sử, chúng ta xây dựng CFG ứng với tiêu chí phủ câu lệnh và phủ nhánh của hàm laNamNhuan có mã nguồn như Hình 2.5a Các câu lệnh được đánh số thứ tự cũng đồng thời là các đỉnh của đồ thị Đỉnh bắt đầu của đồ thị tương ứng với lời gọi hàm Đỉnh 1 là đỉnh quyết định tương ứng với câu lệnh 1 Đỉnh 2 là đỉnh xử lý ứng với câu
lệnh 2 (return -1) Nếu điều kiện tại đỉnh 1 (year<0) là đúng thì tồn tại đường đi
nối đỉnh 1 với đỉnh 2 rồi đi đến đỉnh kết thúc Ngược lại, nếu điều kiện tại đỉnh 1
(year<0) là sai thì đường đi sẽ nối từ đỉnh 1 tới đỉnh 3 tương ứng với câu lệnh 3
(year%400==0) || ((year%4==0) && (year%100!=0)) Đỉnh 3 là đỉnh quyết định
nên nếu điều kiện tại đỉnh 3 là đúng thì tồn tại đường đi nối đỉnh 3 với đỉnh 4 ứng với câu lệnh 4 (return 1) rồi nối đỉnh 4 đến đỉnh kết thúc Ngược lại, nếu điều kiện tại
đỉnh 3 là sai thì đường đi sẽ nối đỉnh 3 đến đỉnh 5 tương ứng với câu lệnh 5 (return 0) rồi nối đỉnh 5 đến đỉnh kết thúc Cuối cùng, ta dựng được đồ thị dòng điều khiển của hàm laNamNhuan thỏa mãn phủ toàn bộ các câu lệnh trên mã nguồn như Hình
2.5b Đây chính là CFG cho tiêu chí phủ câu lệnh và cũng là CFG cho tiêu chí phủ nhánh
Trang 222.3.2 Xây dựng CFG ứng với tiêu chí phủ điều kiện con
Trên các mã nguồn có chứa câu lệnh mang điều kiện phức hợp, chúng ta cần xây dựng CFG ứng với tiêu chí phủ điều kiện con Các điều kiện con thuộc điều kiện phức
hợp sẽ được tách các đỉnh con tương ứng trên CFG Cách xây dựng CFG với tiêu chí
phủ điều kiện con cũng tương tự như xây dựng CFG ứng với tiêu chí phủ câu lệnh
Hình 2.6 Mã nguồn và CFG ứng với tiêu chí phủ điều kiện con của hàm laNamNhuan
Ví dụ, ta cần xây dựng CFG với tiêu chí phủ điều kiện con của hàm laNamNhuan
như Hình 2.6a Trên mã nguồn, câu lệnh 3 chứa ba điều kiện con là
(year%400==0);(year%4==0) và (year%100!=0) nên ta tách đỉnh 3 thành các đỉnh
con 3a, 3b, 3c Đỉnh 1 là đỉnh quyết định, ứng với câu lệnh 1 Nếu điều kiện tại đỉnh 1
(year<0) là đúng thì tồn tại đường đi nối đỉnh 1 với đỉnh 2 tương ứng với câu lệnh 2
(return -1) rồi nối đến đỉnh kết thúc Nếu điều kiện tại đỉnh 1 (year<0) là sai thì đường đi sẽ nối đỉnh 1 với đỉnh 3a (year%400==0) Từ câu lệnh 3, toán tử kết hợp giữa điều kiện con 3a và điều kiện con 3b, 3c là toán tử hoặc "||" Do đó, nếu điều kiện tại đỉnh 3a(year%400==0)là đúng thì ta không cần xét đến các điều kiện còn lại
Ta sẽ có đường đi nối đỉnh 3a với đỉnh 4(return 1) rồi nối đến đỉnh kết thúc
Ngược lại, nếu điều kiện tại đỉnh 3a là sai thì ta cần xét tiếp các điều kiện tại đỉnh 3b
(year%4==0) và 3c (year%100!=0), ta có đường đi nối từ đỉnh 3a với 3b theo nhánh sai của đỉnh 3a Toán tử kết hợp giữa điều kiện con 3b (year%4==0) và 3c
(year%100!=0)là toán tử "&&", nên nếu điều kiện tại hai đỉnh 3b và 3c là đúng thì ta
có đường đi nối các đỉnh 3a(T), 3b(T)và nối với đỉnh 4 (return 1) rồi đi đến đỉnh
kết thúc Nếu một trong hai điều kiện tại đỉnh 3a (year%4==0) hoặc 3b
(year%100!=0) là sai thì đường đi sẽ nối một trong hai đỉnh theo nhánh sai của 3a và 3b nối với đỉnh 5(return 0) rồi nối đỉnh 5 đến đỉnh kết thúc Cuối cùng, ta dựng
được CFG ứng với tiêu chí phủ điều kiện con của hàm như Hình 2.6b
T
T 3b
Trang 232.3.3 Phương pháp xây dựng CFG từ mã nguồn Java
Để xây dựng CFG từ mã nguồn cho mã nguồn Java trong môi trường thực, chúng
ta cần có cấu trúc dữ liệu của mã nguồn tương ứng Cấu trúc này thường được sinh ra bằng cách sử dụng công cụ hỗ trợ JDT(Java Development Tooling) Công cụ này sẽ
phân tích các hàm đầu vào thành các cây cú pháp trừu tượng (Abstract Syntax Tree – AST) Trong bước này, phương pháp tập trung vào việc lấy được danh sách các khai báo hàm số có trong mã nguồn, sử dụng theo API của plugin JDT [3] Khi có được cây AST, chúng ta tiến hành phân tích cây cú pháp trừu tượng để xây dựng CFG cho mã nguồn Java Cuối cùng, chuẩn hóa định dạng các biểu thức trong cây cú pháp trừu tượng để phục vụ cho việc phân tích và quản lý
2.3.3.1 Phân tích mã nguồn
Cây cú pháp trừu tượng (AST) là một cấu trúc mô tả mối quan hệ giữa các thành phần trên mã nguồn Trên cây AST, một lớp (class) bao gồm các thành phần như sau:
- Định nghĩa lớp: Là nút bao gồm các nút con về phạm vi truy cập (public, private,
v.v.), tên lớp và thân lớp Phần thân lớp gồm các nút khai báo thuộc tính và các nút
- Định nghĩa phương thức: là một cây AST con bao gồm các thành phần: định nghĩa
phương thức, khai báo hằng số, biến toàn cục/cục bộ, struct, các câu lệnh trong thân hàm, v.v được thể hiện theo quan hệ cha - con Mỗi AST của một phương thức sẽ có cấu trúc như sau:
o Tên phương thức: Tên được sử dụng để tìm kiếm một phương thức khi nó
được gọi (invoke) trong một câu lệnh ở thân một phương thức khác
o Kiểu trả về: Được sử dụng để sinh loại dữ liệu đầu ra
o Danh sách đối số: Dùng để xác định chính xác phương thức cần gọi tới trong
trường hợp có nhiều hàm trùng tên
o Phần thân phương thức: là một cây AST con tương ứng với từng câu lệnh và
các biểu thức tương ứng trên trong
Trang 242.3.3.2 Xây dựng CFG từ cây cấu trúc trừu tƣợng
Từ cấu trúc cây AST, chúng ta sử dụng một thuật toán để biến đổi cây AST sang dạng đồ thị dòng điều khiển, được mô tả ở Thuật toán 2.1
Thuật toán 2.1: Sinh_G(AST, t)
Đầu vào: AST: cây AST môt tả cấu trúc của hàm cần kiểm thử;
t: tiêu chí kiểm thử
Đầu ra: G: đồ thị dòng điều khiển ứng với độ phủ t,
G là biến toàn cục được khởi tạo là rỗng
Liên kết node với các đỉnh của G
T_AST := các đỉnh thuộc cây AST theo nhánh đúng Sinh_G(T_AST, t)
F_AST :=các đỉnh thuộc cây AST theo nhánh sai Sinh_G(F_ AST, t)
elseif(c là các câu lệnh break, continue, return, goto ) N_ AST := đỉnh liên kết tiếp theo sau c thuộc cây AST
L
L
Trang 25Đầu vào của thuật toán là cây AST môt tả cấu trúc mã nguồn và tiêu chí kiểm thử
t Đầu ra của thuật toán là một đồ thị G mô tả dòng điều khiển của mã nguồn
Đầu tiên, với từng nút c của cây AST được duyệt theo thứ tự top-down (dòng 1) Nếu nút c là đỉnh quyết định (dòng 2) (if…else, for, do…while, v.v.) thì tạo một node mới của G tương ứng với nút c trên cây AST và cập nhật node vào G (dòng 3, 4) Tiếp theo, liên kết node với các đỉnh khác trong đồ thị G (dòng 5) Sau đó, gọi đệ quy (dòng
7, 9) cây AST là T_AST và F_AST của các khối lệnh ứng với nhánh đúng vào nhánh sai (dòng 6, 8) Nếu c là các từ khóa (return, break, continue, …) thì cây AST N_AST được gọi đệ quy (dòng 11, 12) Còn nếu c là một khối các câu lệnh thì cây AST c_AST của c được gọi đệ quy (dòng 14, 15) Nếu c là câu lệnh gán hoặc khai báo thì thì một đỉnh node mới của G được khởi tạo đại diện cho c và thêm các liên kết với các đỉnh khác trong đồ thị (dòng 17, 18, 19) Thuật toán kết thúc khi nút cuối cùng của cây AST được duyệt, ta dựng được đồ thị G mô tả cấu trúc điều khiển của mã nguồn Java
2.4 Sinh đường đi kiểm thử từ đồ thị
Đường đi xuất phát từ đỉnh bắt đầu của CFG, đi qua các đỉnh trong đồ thị theo thứ tự thực hiện câu lệnh đến đỉnh kết thúc được gọi là một đường đi độc lập Một tập
đường đi độc lập trên đồ thị thỏa mãn các tiêu chí kiểm thử gọi là tập đường kiểm thử
Mục tiêu của quá trình sinh các đường kiểm thử là tìm được số đường kiểm thử ít nhất
nhưng đạt được độ phủ tối đa trên đồ thị
Trên mỗi CFG, tập đường kiểm thử được xác định sao cho nó phủ hết các nhánh của đồ thị Theo [7], số đường đi của chương trình ứng với đồ thị dòng điều khiển của
nó được tính bằng số đỉnh quyết định của CFG tương ứng cộng 1 hoặc bằng số cạnh trừ số đỉnh của CFG tương ứng cộng 2
2.4.1 Sinh đường đi thỏa mãn tiêu chí phủ câu lệnh
Để sinh các đường kiểm thử thỏa mãn tiêu chí phủ câu lệnh từ CFG tương ứng,
chúng ta tìm các đường đi sao cho mỗi đỉnh được "ghé thăm" ít nhất một lần (đồng nghĩa với mỗi câu lệnh được duyệt qua ít nhất một lần)
Ví dụ, ta cần sinh đường kiểm thử thỏa mãn tiêu chí phủ câu lệnh cho hàm
laNamNhuan có CFG được hiển thị ở Hình 2.7 Trên đồ thị, ta xác định được ba
đường đi để mỗi đỉnh của đồ thị được đi qua ít nhất một lần, các đường được liệt kê như sau:
p1: 1(T), 2
p2: 1(F), 3(T), 4
p3: 1(F), 3(F), 5
Trang 26Hình 2.7 Mã nguồn và CFG ứng với tiêu chí phủ câu lệnh của hàm laNamNhuan
Rõ ràng, tất cả các đỉnh (tương ứng với câu lệnh từ 1 đến 5) đều xuất hiện trên tập đường đi này, nên đây chính là tập đường kiểm thử thỏa mãn tiêu chí phủ câu lệnh
2.4.2 Sinh đường đi thỏa mãn tiêu chí phủ nhánh
Sinh các đường kiểm thử thỏa mãn tiêu chí phủ nhánh từ CFG là tìm tập đường
đi sao cho các đỉnh quyết định trên CFG đều được duyệt qua cả hai nhánh đúng và sai
Ví dụ, CFG của hàm laNamNhuan ở Hình 2.7 có hai đỉnh quyết định là đỉnh 1 và đỉnh
3 Để đạt được tiêu chí phủ nhánh chúng ta cần 2+1=3 đường đi Thứ tự các đường đi
như sau:
p1: 1(T), 2
p2: 1(F), 3(T), 4
p3: 1(F), 3(F), 5
Ta thấy, các đường đi này đều đi qua hai nhánh của đỉnh 1 và đỉnh 3 Vậy đây
chính là tập đường đi kiểm thử thỏa mãn tiêu chí phủ nhánh của hàm laNamNhuan
2.4.3 Sinh đường đi thỏa mãn tiêu chí phủ điều kiện con
Với CFG của tiêu chí phủ điều kiện con, đường kiểm thử sẽ được xác định sao cho nó phủ hết các nhánh của mọi đỉnh quyết định trên đồ thị Ví dụ, trên CFG ứng
với tiêu chí phủ điều kiện con của hàm laNamNhuan mô tả Hình 2.8 có 4 đỉnh quyết định là 1, 3a, 3b, 3c nên ta cần 4+1=5 đường đi để đạt 100% tiêu chí phủ điều kiện
con Các đường đi được liệt kê như sau:
Trang 27Hình 2.8 Mã nguồn và CFG ứng với tiêu chí phủ điều kiện con của hàm laNamNhuan
Tập các đường đi từ p1 đến p5 đều đã đi qua cả hai nhánh đúng và sai của các đỉnh quyết định 1, 3a, 3b, 3c nên đây chính là tập đường đi kiểm thử thỏa mãn tiêu chí phủ điều kiện con của hàm laNamNhuan
2.4.4 Phương pháp sinh đường đi kiểm thử trên đồ thị
Từ CFG đã xây dựng được ở Thuật toán 2.1, luận văn tiến hành nghiên cứu phương pháp sinh tập các đường kiểm thử trên đồ thị của mã nguồn Java trong môi trường thực dựa vào phương pháp sinh đường kiểm thử của Mc-Cabe đề xuất trong [7] Ý tưởng của phương pháp là tìm đường đi ngắn nhất trên CFG bằng các duyệt đồ
thị theo nhánh fasle tại các đỉnh quyết định Sau đó thay đổi đỉnh xuất phát và tìm
đường đi ngắn nhất tiếp theo Từng đường đi sẽ được đưa vào tập đường kiểm thử cho đến khi nó phủ hết toàn bộ các nhánh trên đồ thị Thuật toán sinh đường kiểm thử dựa trên phương pháp nghiên cứu được mô tả ở Thuật toán 2.2
Đầu vào của thuật toán là một đồ thị dòng điều khiển G mô tả cấu trúc của hàm cần kiểm thử Đầu ra của thuật toán là tập các đường kiểm thử trên đồ thị G Đầu tiên, khởi tạo biến Path để lưu các đường kiểm thử trên đồ thị (dòng 1) Duyệt đồ thị theo nhánh false qua các đỉnh quyết định của đồ thị và lưu vào tập Path (dòng 2, 3) Tiếp theo, gọi P là tập các đỉnh quyết định trên đường kiểm thử Path và Visited là tập các
đỉnh quyết định đã được duyệt theo cả hai nhánh (dòng 4,5) Với các đỉnh quyết định
thuộc P (dòng 6), từ một đỉnh u bất kỳ trên P và đỉnh v liền kề với u sao cho cạnh (u,v) chưa có trong Path (dòng 7,8), ta tìm đường đi ngắn nhất qua (u,v) và cập nhật vào tập đường kiểm thử Path (dòng 9, 10) ta được đường kiểm thử mới là d Bổ sung các đỉnh quyết định trên d vào P (dòng 11) Cuối cùng, giải phóng đỉnh u khỏi tập P và đánh
dấu là đỉnh u đã được duyệt qua cả hai nhánh (dòng 12,13) Lặp lại quá trình đến khi
các đỉnh quyết định thuộc P được duyệt hết Thuật toán kết thúc khi chúng ta thu được tập đường kiểm thử Path trên đồ thị G
T
T 3b
Trang 28Thuật toán 2.2: Sinh_Path(G)
Đầu vào: G: đồ thị dòng điều khiển
Đầu ra: Path: tập các đường đi độc lập của đồ thị G
shortestPath := đường đi qua các nhánh false của G
Cập nhật shortestPath vào Path
P := tập các điểm quyết định thuộc shortestPath
Visited := Ø tập các điểm quyết định đã được ghé thăm
while (P != Ø) do
u := một đỉnh quyết định thuộc P
v := đỉnh liền kề với u sao cho cạnh (u,v) chưa có trong Path
d := đường đi ngắn nhất qua (u, v)
Bổ dung các đỉnh quyết định thuộc d vào P
Loại bỏ đỉnh u khỏi tập P
Bổ sung đỉnh u vào tập Visited
end while
2.5 Sinh ca kiểm thử từ đường đi
Để kiểm tra sự đúng đắn của các đường kiểm thử trên đồ thị, chúng ta tiến hành thực hiện ca kiểm thử trên mỗi đường đi bằng cách sinh các dữ liệu kiểm thử và phân tích mã nguồn để có được giá trị đầu ra mong muốn (EO) Nếu sau khi thực hiện các
ca kiểm thử trong môi trường thực, giá trị đầu ra thực tế (RO) trùng với giá trị đầu ra mong muốn thì ca kiểm thử ứng với đường đi là thực hiện được Ngược lại, ca kiểm
thử ứng với đường đi là có lỗi (fail), đường kiểm thử là không thực hiện được hoặc là
một phần của đường đi khác Dữ liệu kiểm thử được sinh ra dựa vào việc giải hệ ràng buộc bằng công cụ SMT-Solver như được mô tả chi tiết trong [5]
2.5.1 Sinh dữ liệu kiểm thử
Dữ liệu kiểm thử là bộ giá trị đầu vào được chọn để thực thi ca kiểm thử trên đường đi Với mỗi đường kiểm thử, để sinh bộ dữ liệu kiểm thử tương ứng, chúng ta
sẽ giải hệ ràng buộc với các biến là tham số của đối tượng cần kiểm thử sao cho giá trị các biến thỏa mãn các điều kiện trên đường đi
Ví dụ, để sinh dữ liệu kiểm thử cho tập đường kiểm thử ứng với tiêu chi phủ điều
kiện con của hàm laNamNhuan đã tìm được ở Mục 2.4.3, liệt kê như dưới đây, ta sẽ
Trang 29phân tích và giải các hệ ràng buộc trên mỗi đường đi sao cho điều kiện tại các điểm quyết định được thỏa mãn Bảng 2.5 là dữ liệu kiểm thử cho mỗi đường đi
- Xét đường đi p1: 1(T), 2 Để đường đi này được thi hành thì nghiệm của hệ ràng
buộc ứng với đường đi này là các giá trị nguyên sao cho điều kiện tại đỉnh quyết định 1 (year<0) là đúng Giả sử ta chọn giá trị year = - 1 làm dữ liệu kiểm thử của đường đi này
- Xét đường đi p2: 1(F), 3a(T), 4 Để đường đi này được thi hành thì nghiệm của hệ
ràng buộc ứng với đường đi này là các giá trị nguyên thỏa mãn điều kiện tại đỉnh
quyết định 1(year<0) là sai và điều kiện tại đỉnh quyết định 3a - (year%400==0)
là đúng Giả sử ta chọn giá trị year = 2000 làm dữ liệu kiểm thử của đường đi này
- Xét đường đi p3: 1(F), 3a(F), 3b(T), 3c(T),4 tương tự với cách làm trên ta chọn year =1996 để các điều kiện tại đỉnh quyết định 1 và 3a là sai; điều kiện tại đỉnh
3b (year%4==0) và điều kiện tại đỉnh 3c (year%100!=0) là đúng Giả sử ta chọn year = 1996 làm dữ liệu kiểm thử của đường đi này
- Tương tự, với đường đi p4: 1(F), 3a(F), 3b(T), 3c(F), 5 Ta chọn giá trị year =
1200 làm dữ liệu kiểm thử để điều kiện tại đỉnh 3b (year%4==0) là đúng và điều
kiện tại các đỉnh 1, 3a, 3c là sai
- Cuối cùng, với đường đi p5: 1(F), 3a(F), 3b(F), 5 Để đường đi được thi hành thì
nghiệm của hệ ràng buộc ứng với đường đi này là giá trị nguyên sao cho điều kiện
tại các đỉnh đỉnh 1, 3a, 3b là sai Ta chọn giá trị year = 2001 làm dữ liệu kiểm thử
Bảng 2.5 Dữ liệu kiểm thử cho tiêu chí phủ điều kiện con của hàm laNamNhuan
Trang 302.5.2 Sinh đầu ra mong muốn
Đầu ra mong muốn (Expected Output - EO) của ca kiểm thử là giá trị đầu ra mà
ta mong muốn của ca kiểm thử sau khi ca kiểm thử được thực thi Với các phương pháp hiện tại, dựa trên đặc tả của bài toán, chúng ta phân tích giá trị đầu vào ứng với đường thi hành để xác định giá trị đầu ra mon muốn Quá trình này thường được tiến hành thủ công và rất khó tự động hóa Tuy nhiên, trong luận văn này, giá trị đầu ra mong muốn chính là giá trị thực tế có được ứng với đầu vào tương ứng vì mã nguồn
do giáo viên cung cấp là mã nguồn chuẩn (không có lỗi) Vì vậy, chúng ta dễ dàng tự động hóa việc sinh giá trị đầu ra mong muốn
Ví dụ, ta để tim đầu ra mong muốn cho các ca kiểm thử của hàm laNamNhuan ở bảng 2.5 Khi chạy các ca kiểm thử với các giá trị đầu vào là mã nguồn chuẩn, ta được
kết quả đầu ra mong muốn, được ghi lại trên Bảng 2.6
Bảng 2.6 Các ca kiểm thử cho tiêu chí phủ câu lệnh của hàm laNamNhuan
2.6 Sinh các ca kiểm thử giá trị biên và vòng lặp
Các ca kiểm thử ứng với ba tiêu chí kiểm thử là phủ câu lệnh, phủ nhánh, phủ điều kiện con đã đảm bảo phủ được tất cả các nhánh trên CFG Tuy nhiên, các ca kiểm thử này lại không kiểm tra được các lỗi ứng với các tình huống có đặc tả và không được lập trình (thương được phát hiện bởi phương pháp kiểm thử hộp đen) Chẳng hạn, trong khi lập trình, các học sinh thường viết sai câu lệnh điều kiện hoặc không viết câu lệnh kiểm tra các giá trị biên, chính vì vậy, để có một bộ dữ liệu kiểm thử đủ tốt, chúng ta cần thiết kế thêm các ca kiểm thử để kiểm thử các giá trị biên của hàm Thêm nữa, với mã nguồn có chứa vòng lặp, cho dù đã có được các ca kiểm thử thỏa mãn các tiêu chí phủ, thì lỗi vẫn có thể xảy ra bên trong vòng lặp Nguyên nhân là do, các đường đi ứng với các tiêu chí kiểm thử chỉ đi qua vòng lặp một lần nên không thể phát hiện và kiểm soát hết các lỗi khi vòng lặp thực thi nhiều lần Chính vì vậy, với những hàm có chứa vòng lặp, chúng ta cần sinh thêm các ca kiểm thử cho vòng lặp nhằm phát hiện lỗi