JPF là công cụ kiểm chứng phần mềm hỗ trợ nhiều tính năng phục vụ cho việc kiểm chứng. Một trong số đó chính là đo độ phủ của các ca kiểm thử với phương thức được thực thi. Phần mở rộng Listener là một phần mở rộng quan trọng, nó có nhiệm vụ theo dõi mã nguồn và kiểm soát thực thi chương trình. Để thực hiện đo độ phủ của bộ các ca kiểm thử chúng ta có thể sử dụng một tính năng trong phần mở rộng này cụ thể là sử dụng lớp CoverageAnalyzer. Lập trình viên sẽ cấu hình file config nhằm gọi sử dụng đối tượng của lớp
25
CoverageAnalyzer, đối tượng này sẽ đọc mã nguồn của một lớp cần kiểm tra kết hợp với các ca kiểm thử để kiểm thử các phương thức trong lớp. Qua quá trình xử lý kết quả đầu ra đã chỉ rõ số điều kiện đã phủ trên tổng số điều kiện theo tiêu chuẩn bao phủ điều kiện (condition coverage).
Hình 3.6: Quy trình kiểm tra độ phủ hàm sử dụng JPF CoverageAnalyzer
Trong lớp CoverageAnalyzer có tham số branch tham số này có chức năng đếm số nhánh đã được phủ dựa trên tiêu chuẩn bao phủ điều kiện (Condition coverage). Lấy ví dụ hàm exam như sau :
public static float exam(int a, int b, int c, int d) {
1: if (a == 0) 2: return 0; 3: int x = 0; 4: if ((a == b) || (c == d)) 5: x = 1; 6: return x + 2; }
Hình 3.7: Đồ thị luồng điều khiển của hàm exam Bảng 3.1: Bộ test theo tiêu chuẩn bao phủ điều kiện của hàm exam Bảng 3.1: Bộ test theo tiêu chuẩn bao phủ điều kiện của hàm exam
ID Test Path Input EO
Tc1 1, 2 0,1,2,3 0 Tc2 1,3,4T1(F),4T2(T),5,6 1,2,2,2 3 Tc3 1,3,4T1(T),5,6 1,1,2,3 3 Tc4 1,3,4T1(F),4T2(F),6 1,2,4,3 2 Sinh các ca kiểm thử Thực hiện các ca kiểm thử Đo độ phủ JPF CoverageAnalyzer Đơn vị chƣơng trình Tiêu chuẩn bao phủ Xác định các đƣờng đi Xây dựng đồ thị luồng điều khiển 2 3 5 4T1 4T2 6 1
26
Sau khi kiểm thử với các ca kiểm thử thỏa mãn tiêu chuẩn bao phủ điều kiện (condition coverage) trong bảng 3.1, đo độ phủ với JPF CoverageAnalyzer kết quả hiển thị trong hình 3.8 tại cột branch là 1.0 (3/3)
Hình 3.8: Minh họa kết quả đo độ phủ sử dụng JPF CoverageAnalyzer
JPF CoverageAnalyzer đo độ phủ bằng cách đếm số điều kiện cần kiểm tra trong hàm, nếu điều kiện phức tạp gồm nhiều điều kiện con chương trình sẽ đếm riêng rẽ từng điều kiện con đó. Nhìn vào hàm exam thấy được rằng có tất cả 3 quyết định (a==0) ,(a==b) và (c==d), ba quyết định này đều đã được phủ hết hai nhánh true, false mỗi nhánh ít nhất 1 lần cho mỗi điều kiện vì vậy độ đo thu được tại cột branch sẽ là 1.0 (3/3) như trong hình 3.8.
Tuy nhiên nhược điểm của phương pháp này đó là khi sử dụng tiêu chuẩn bao phủ câu lệnh (statement coverage) và bao phủ nhánh(branch coverage) kết quả không thực sự rõ ràng.
Khi đo độ bao phủ sử dụng tiêu chuẩn bao phủ lệnh tức là trong thiết kế các ca kiểm thử luôn cố gắng bao phủ tối đa câu lệnh trong mã nguồn với số test case ít nhất có thể. Vẫn lấy ví dụ hàm exam. Xây dựng bộ test case theo tiêu chuẩn bao phủ câu lệnh (statement coverage) như trong bảng 3.2 :
Bảng 3.2: Bộ test theo tiêu chuẩn bao phủ câu lệnh của hàm exam
ID Test Path Input EO(Expected
output)
Tc1 1(T), 2 0,1,2,3 0
Tc2 1(F),3,4(T),5,6 1,1,2,3 3
Sử dụng công cụ Java Pathfinder để đo bao phủ dòng lệnh, kiểm tra các dòng mã nguồn đã được thực thi thu được báo cáo kết xuất như hình 3.9:
27
Hình 3.9: Kết quả kiểm tra độ phủ câu lệnh của hàm exam
Kết quả nhận được trong hình 3.9 không thể hiện rõ đã phủ hết câu lệnh hay chưa. Cột branch có giá trị 0.33(1/3) thể hiện chỉ có một điều kiện đã được phủ. Với kết quả trên, chúng ta thấy có điều kiện(a == 0) là đã được phủ vì khi thực thi chương trình đều đã đi qua hai nhánh true và false của biểu thức này, còn điều kiện (a == b) và (c == d) chưa được phủ hết.
Tương tự khi đo độ bao phủ với tiêu chuẩn bao phủ nhánh (branch coverage). Tiêu chuẩn bao phủ nhánh là kiểm thử sao cho mỗi điều kiện được thực hiện ít nhất một lần trường cả hai nhánh true và false không cần chia nhỏ nếu điều kiện phức tạp. Quay trở lại với ví dụ hàm exam, khi sử dụng tiêu chuẩn bao phủ nhánh thì đồ thị luồng điều khiển không thay đổi, chúng tôi vẫn sử dụng mã nguồn hàm exam và đồ thị trong hình 3.7. Bảng 3.3 mô tả các trường hợp cần kiểm thử để đạt được 100% bao phủ nhánh.
Bảng 3.3: Bộ test theo tiêu chuẩn bao phủ nhánh của hàm exam
ID Test Path Input EO
Tc1 1(T), 2 0,1,2,3 0
Tc2 1(F),3,4(T),5,6 1,1,2,3 3
Tc3 1(F),3,4(F),6 1,2,2,3 2
Sử dụng công cụ JPF CoverageAnalyzer đo bao phủ nhánh, báo cáo kết quả như trong hình 3.10:
Với các ca kiểm thử ở bảng 3.3 kết quả nhận được trong hình 3.10 tại cột
branch của có giá trị 0.67(2/3). Giá trị này không thực sự rõ ràng khi thể hiện đã bao phủ nhánh. Người dùng phải xem lại code và đối chiếu với kết quả trong hình 3.10 để kiểm tra những nhánh đã phủ và chưa phủ, việc này mất thời gian và đôi khi không khả thi với các hàm phức tạp.
28
Hình 3.10: Kết quả kiểm tra độ phủ nhánh của hàm exam
Khi kiểm tra độ phủ sử dụng JPF CoverageAnalyzer chúng ta có thể biết được số điều kiện phủ, số hàm được thực thi trong lớp với bộ test theo tiêu chuẩn phủ điều kiện, tuy nhiên chúng không rõ ràng. Chỉ số branch chỉ thể hiện số điều kiện đã được phủ mà không chỉ rõ nhánh nào chưa phủ, nhánh chưa phủ đó nằm ở vị trí nào trong hàm, bên cạnh đó kiểm thử vòng lặp cũng gặp trở ngại bởi khi kiểm thử vòng lặp không chỉ đo chỉ số độ phủ mà còn phải xác định xem vòng lặp thực thi bao nhiêu lần, mỗi lần có phát sinh lỗi không.