Kiểm
thử phần mềm là một trong hai phương pháp đảm bảo chất lượng phổ biến cho phần
mềm: phương pháp kiểm chứng phần mềm và kiểm thử phần mềm. Bên trong kiểm thử
phần mềm, ta có nhiều cách tiếp cận để kiểm thử phần mềm như kiểm thử hộp đen,
kiểm thử hộp trắng và kiểm thử hộp xám. Trong khi kiểm thử hộp đen tập trung
vào phân tích yêu cầu của phần mềm để sinh được các ca kiểm thử, kiểm thử hộp
trắng dựa vào mã nguồn của đơn vị được kiểm thử để sinh dữ liệu kiểm thử cho
đơn vị đó. Trong khi đó, kiểm thử hộp xám là sự kết hợp của hai loại kiểm thử hộp
đen và hộp trắng. Từ bản chất của hai loại hình kiểm thử hộp đen và hộp trắng
như vậy, kiểm thử hộp đen được sử dụng để tìm lỗi của phần mềm so với yêu cầu của
nó. Trong khi đó, tuy kiểm thử hộp trắng được sử dụng để tìm lỗi của phần mềm,
ta tập trung vào việc phân tích mã nguồn, sinh các ca kiểm thử nhằm phủ được mã
nguồn theo các tiêu chuẩn phủ khác nhau. Với việc cố gắng phủ được các loại độ phủ khác nhau, ta tin rằng
những dữ liệu kiểm thử của ta sẽ kiểm thử được toàn bộ các trường hợp được cài
đặt trong mã nguồn. Từ đó, ta hy vọng là tìm được lỗi của phần mềm tiềm ẩn
trong các cài đặt của nó.
Bài
này giới thiệu một số loại độ phủ phổ biến được sử dụng trong kiểm thử hộp trắng
và theo luồng điều khiển (control flow graph – CFG) trong lĩnh vực kiểm thử phần
mềm. Mỗi loại độ phủ được định nghĩa dựa trên các thành phần khác nhau của đồ
thị như câu lệnh, các nhánh thực hiện chương trình, các điều kiện quyết định
nhánh, các điều kiện con, hoặc sự kết hợp của chúng, v.v. Mục tiêu của các phương pháp sinh dữ liệu kiểm
thử là sinh tập dữ liệu kiểm thử sao cho đạt được mức độ phủ tối đa trong khi số
lượng ca kiểm thử cần thiết là tối thiểu. Sau đây là một số loại độ đo phổ biến
thường được sử dụng [LeeCopeland2004]:
Độ
phủ cấp 1 (C1) (độ phủ câu lệnh): Mỗi câu lệnh của hàm được thực hiện tối
thiểu một lần sau khi chạy các ca kiểm thử. Ví dụ, với hàm getAverage
sau đây, ta chỉ cần 1 ca kiểm thử (arr[0] = 5, n = 1) để phủ được toàn bộ câu lệnh
của nó. Người ta nói rằng, việc không kiểm thử chương trình để đạt được độ phủ
100% các câu lệnh là một việc làm không chuyên nghiệp, thiếu trách nhiệm trong
nghề nghiệp của ta.
float getAverage(int arr[], int n)
{
float avg = 0;
int temp = 0;
if (n > 0)
{
for (int i = 0; i < n; i++)
{
temp += arr[i];
}
avg = temp / n;
}
return avg;
}
|
Độ
phủ cấp 2 (C2) (Độ phủ nhánh): Độ phủ này còn được biết đến với tên độ
phủ quyết định (decision coverage). Cả hai nhánh đúng và sai ở các đỉnh điều
kiện trong đồ thị luồng điều khiển của đơn vị cần kiểm thử được thực hiện ít nhất
một lần. Ví dụ, với hàm getAverage ở trên, ta cần hai ca kiểm thử sau để
phủ được hết các nhánh của hàm: (arr = null, n = 0), (arr[0] = 5, n = 1).
Độ
phủ cấp 3 (C3) (Độ phủ điều kiện con, Modified condition/decision coverage -
MC/DC): Với những hàm có chứa câu điều kiện phức tạp với nhiều điều kiện
con, việc đảm bảo toàn bộ các điều kiện con được kiểm tra là một tiêu chí quan
trọng. Việc này để đảm bảo các điều kiện được viết trong hàm là có chủ đích và
kiểm soát được. Ví dụ, với điều kiện (a == 2) && (b > 3), ta nói rằng
điều kiện này có hai điều kiện con là (a == 2) và (b > 3). Như ta đã biết, mỗi
điều kiện con sẽ có hai nhánh đúng và sai. Như vậy, với điều kiện này, ta có bốn
nhánh. Để phủ được theo độ phủ cấp 3, ta cần bốn ca kiểm thử sau: (a = 2, b =
4), (a = 3, b = 4), (a = 2, b = 3), (a = 3, b = 3).
Đôi
khi, ta cũng có xét một độ phủ với mức độ yêu cầu thấp hơn là độ phủ điều kiện
(condition coverage) (mỗi điều kiện được tính toán ít nhất một lần).
Ví dụ, với điều kiện (a == 2) && (b > 3), ta chỉ cần hai ca kiểm
thử để đạt độ phủ này (a = 2, b = 4) (ca kiểm thử này b > 3 không được tính
toán), và (a = 3, b = 4) (vì a = 3 nên b > 3 được tính toán).
Độ
phủ cấp 4 (C4) (Độ phủ đa điều kiện): Trong trường hợp này, ta cần dựa vào
hiểu biết của ta với bản thân ngôn ngữ lập trình và trình biên dịch để đảm bảo
rằng toàn bộ điều kiện con của lệnh điều kiện được tính toán và các ca kiểm thử
được sinh ra phải phủ được cả hai nhánh TRUE và FALSE của toàn bộ các lệnh điều
kiện con. Ở một mức độ nào đó, độ phủ này giống với độ phủ C3 được trình bày ở trên. Khi đạt được độ
phủ này, ta chắc chắn đã đạt được độ phủ C3.
Độ
phủ cấp 5 (C5) (Độ phủ vòng lặp): Trong trường hợp hàm cần kiểm thử có chứa
lệnh vòng lặp mà vòng lặp này làm cho số lượng đường thi hành của hàm trở nên
vô hạn. Ta có thể giảm số lượng ca kiểm thử này về một số trường hợp sau.
Trường
hợp 1: vòng lặp không được thực hiện lần nào.
Trường
hợp 2: vòng lặp được thực hiện một lần.
Trường
hợp 3: vòng lặp được thực hiện n lần với n là một số nhỏ đại diện cho một giá
trị lặp thường gặp.
Trường
hợp 4: thực thi vòng lặp một số m lần với m là số lớn nhất có thể. Thêm vào đó,
ta có thể thử với số lần lặp là m – 1 và m + 1 để có thể kiểm tra được nhiều
trường hợp thực thi hơn.
Độ
phủ cấp 6 (C6) (Độ phủ đường thi hành): Với những hàm không chứa vòng lặp,
thường thì số lượng đường thi hành không quá lớn. Vì vậy, ta có thể sinh các ca
kiểm thử để có thể phủ được toàn bộ đường thi hành tương ứng của hàm. Với các
hàm có chứa vòng lặp, số lượng đường thi hành có thể rất lớn phụ thuộc vào vòng
lặp của hàm. Vì vậy, ta có thể áp dụng độ phủ C5 đã được trình bày ở trên để
sinh ca kiểm thử.
[LeeCopeland2004]
Copeland Lee, A practitioner’s guide to software test design, Artech House,
Inc., Norwood, MA, USA, 2003
(https://www.facebook.com/thayvietkiemthu/posts/112786171353610)