Sunday, March 27, 2022

Một số độ phủ phổ biến trong kiểm thử phần mềm

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)

Kiểm thử cặp đôi thông minh

  Kiểm thử cặp đôi thông minh (pairwise testing) là một trường hợp đặc biệt của phương pháp kiểm thử tổ hợp. Trong phương pháp kiểm thử cặp ...