You are on page 1of 55

TRƯỜNG ĐẠI HỌC THƯƠNG MẠI

Khoa HTTT Kinh tế và THMĐT


Bộ môn Công nghệ thông tin

Chương 3

THIẾT KẾ CA KIỂM THỬ

1
Nội dung

1. Kiểm thử chức năng


—Kiểm thử giá trị biên
—Kiểm thử lớp tương đương
—Kiểm thử bảng quyết định
2. Kiểm thử cấu trúc
—Tổng quan
—Kiểm thử luồng điều khiển
—Kiểm thử luồng dữ liệu

2
Tổng quan

 Kiểm thử cấu trúc


—Giới thiệu
—Kiểm thử luồng điều khiển
• DD-Paths
• Test Coverage Metrics
• Basis Path Testing
• Guidelines and Observations
—Kiểm thử luồng dữ liệu
—Phương pháp lai & Thảo luận

3
Kiểm thử cấu trúc

 Thuật ngữ tiếng Anh: glass box, structural,


clear box and open box testing.
 Thuật ngữ tiếng Việt: kiểm thử hộp trắng
 Là kỹ thuật kiểm thử trong đó tri thức tường
minh về hoạt động bên trong của phần mềm
được dùng để xây dựng các ca kiểm thử
 Kiểm thử hộp trắng dựa trên mã nguồn để xây
dựng các ca kiểm thử và kiểm tra đầu ra.

4
Kiểm thử cấu trúc

 Kiểm thử cấu trúc dựa trên:


—Các định nghĩa chặt chẽ liên quan đến ngữ nghĩa của
ngôn ngữ lập trình
• Luồng điều khiển, luồng dữ liệu, mục tiêu, tiêu chuẩn bao phủ
—Phân tích toán học
• Phân tích đồ thị, đường đi
—Các phép đo chính xác
• Bao phủ

5
Định nghĩa đồ thị chương trình

“Cho một chương trình trong ngôn ngữ mệnh lệnh, đồ thị
chương trình của nó là một đồ thị có nhãn, có hướng
trong đó
- Đỉnh là các nhóm lệnh hoặc một phần của một lệnh
- Cạnh là luồng điều khiển”

6
Các thành phần của đồ thị

7
Đồ thị chương trình

 Nếu i và j là hai đỉnh thì có một cạnh từ i đến j trong


đồ thị chương trình nếu và chỉ nếu lệnh ở đỉnh j có
thể chạy ngay sau (các) lệnh ở đỉnh i.
 Nhóm các lệnh tạo thành một đỉnh trong đồ thị
chương trình gọi là khối cơ bản.
 Dễ dàng xây dựng các khối cơ bản và tạo đồ thị
chương trình

8
Ví dụ các khối cơ bản
FindMean (FILE ScoreFile)
{ float SumOfScores = 0.0;
int NumberOfScores = 0;
1
float Mean=0.0; float Score;
Read(ScoreFile, Score);
2 while (! EOF(ScoreFile) {
3 (Score > 0.0 ) {
if
SumOfScores = SumOfScores + Score;
4
NumberOfScores++;
}
5
Read(ScoreFile, Score); 6
}
/* Compute the mean and print the result */
7 if (NumberOfScores > 0) {
Mean = SumOfScores / NumberOfScores;
printf(“ The mean score is %f\n”, Mean); 8
} else
printf (“No scores found in file\n”); 9
} 9
Sơ đồ khối

Start

F
2
T
3
T F
4 5

7
T F
8 9

Exit
10
Đồ thị chương trình

11
Đồ thị chương trình và đường đi?

1. x = z+5
2. z = 4*3 - y
3. if(x > z) goto A;
4. for( u=0; u < x; u++) {
5. z = z+1;
6. };
7. A: y = z + k

12
Các đường kiểm thử
1. x = z+5 1
2. z = 4*3 - y
3. if(x > z) goto A; x = z+5 Một số đường kiểm thử:
4. for( u=0; u < x; u++) z = 4*3 -y 1, 2, 3, 4, 6, 7
{ 1, 2, 3, 4, 5, 4, 6, 7
5. z = z+1; 1, 2, 6, 7
6. }; x>z 2
7. A: y = z + k t

f 6
R1
R2
3
y = z+k
5 t f
u=0
z = z+1
u++ R3 7
4
u<x

Ví dụ về đồ thị và đường kiểm thử 13


Ví dụ

14
Độ đo kiểm thử

 Đo mức độ bao phủ chương trình của một tập


ca kiểm thử cho trước
 Mức độ bao phủ của một bộ kiểm thử (tập các
ca kiểm thử) được đo bằng tỷ lệ các thành
phần thực sự được kiểm thử so với tổng thể
sau khi đã thực hiện các ca kiểm thử
 Độ bao phủ càng lớn thì độ tin cậy của bộ
kiểm thử càng cao
 Mục tiêu: số ca kiểm thử tối thiểu nhưng đạt
độ bao phủ tối đa.
15
Ba độ đo kiểm thử phổ biến

 Độ đo kiểm thử cấp 1 (C1): mỗi câu lệnh được


thực hiện ít nhất một lần sau khi chạy bộ kiểm
thử.
 Độ đo kiểm thử cấp 2 (C2): mỗi điểm quyết định
trong đồ thị dòng điều khiển đều được thực hiện
ít nhất một lần cho cả hai nhánh đúng và sai.
 Độ đo kiểm thử cấp 3 (C3): với các điều kiện
phức tạp (chứa nhiều điều kiện cơ bản), mỗi
điều kiện con cần thực hiện ít nhất một lần cho
cả hai nhánh đúng và sai.

16
Độ đo kiểm thử cấp 1 (C1)
 Mỗi câu lệnh được thực hiện ít nhất một lần
sau khi chạy bộ kiểm thử.

17
Độ đo kiểm thử cấp 2 (C2)
 Mỗi điểm quyết định trong đồ thị dòng điều khiển đều được
thực hiện ít nhất một lần cho cả hai nhánh đúng và sai

18
Độ đo kiểm thử cấp 3 (C3)
 Với các điều kiện phức tạp (chứa nhiều điều kiện cơ bản), mỗi điều
kiện con cần thực hiện ít nhất một lần cho cả hai nhánh đúng và sai.

19
Quy trình kiểm thử đơn vị
dựa trên độ đo

20
Ví dụ các ca kiểm thử để đạt C1

21
Ví dụ các ca kiểm thử để đạt C2

22
Ví dụ các ca kiểm thử để đạt C3

23
Kiểm thử vòng lặp

 Lệnh lặp đơn giản: đơn vị chương trình chứa


đúng một vòng lặp
 Lệnh lặp liền kề: đơn vị chương trình chứa
các lệnh lặp kế tiếp nhau
 Lệnh lặp lồng nhau: đơn vị chương trình chứa
các vòng lặp chứa các lệnh lặp khác

24
Chương trình chỉ có lệnh lặp
đơn giản
Cần số ca kiểm thử tương ứng với các trường hợp:

 Vòng lặp thực hiện 0 lần


 Vòng lặp thực hiện 1 lần
 Vòng lặp thực hiện 2 lần (2<k<n-1, n là số lần lặp
tối đa của vòng lặp)
 Vòng lặp thực hiện k lần
 Vòng lặp thực hiện n-1 lần
 Vòng lặp thực hiện n lần
 Vòng lặp thực hiện n+1 lần
25
Ví dụ

Các ca kiểm thử


cho hàm average
với độ đo C3:

26
Ví dụ

Các ca kiểm thử


cho hàm average
với kiểm thử
vòng lặp:

27
Nội dung

1. Kiểm thử chức năng


—Kiểm thử giá trị biên
—Kiểm thử lớp tương đương
—Kiểm thử bảng quyết định
2. Kiểm thử cấu trúc
—Tổng quan
—Kiểm thử luồng điều khiển
—Kiểm thử luồng dữ liệu

28
Ý tưởng của kiểm thử luồng dữ
liệu
 Kiểm thử luồng dữ liệu liên quan đến việc chọn
đường đi với mục tiêu bao phủ các cặp gán
(definition) và dùng (use) dữ liệu, được gọi là
các tiêu chuẩn luồng dữ liệu
 Qui trình tổng quát của kiểm thử luồng dữ liệu
là:
—Vẽ đồ thị luồng dữ liệu cho chương trình
—Chọn tiêu chuẩn kiểm thử luồng dữ liệu
—Xác định các đường đi trong đồ thị để thỏa mãn tiêu chuẩn
lựa chọn (all-defs, all-uses, all-P-uses/some-C-uses, v.v..)
—Tạo các ca kiểm thử cho các đường đi đã xác định
Đỉnh gán

 Đỉnh n trong CFG của chương trình P là đỉnh


gán của biến v, viết là DEF(v, b), nếu và chỉ
nếu giá trị của v được xác định không mơ hồ
tại lệnh ở đỉnh n
Đỉnh dùng

 Đỉnh n trong đồ thị CFG của chương trình P là


đỉnh dùng của biến v, viết là USE(v, n), nếu và
chỉ nếu giá trị của biến v được dùng ở lệnh tại
đỉnh n.
—Một đỉnh dùng là dùng vị từ (predicate), ký hiệu P-use
nếu và chỉ nếu lệnh tương ứng ở đỉnh n là lệnh vị từ
—Trái lại, nó là dùng tính toán, ký hiệu C-use
 Đỉnh tương ứng với P-use luôn có bậc ra >= 2
và các đỉnh tương ứng với C-use luôn có bậc
ra <= 1
Ví dụ luồng điều khiển có chú
thích
 Luồng dữ liệu cho biến Z:
1 INPUT X,Y
Z:= X+Y
Y:= X-Y
3 IF Z>=0 GOTO SAM
p JOE LOOP B(U)?
4 JOE: Z:=Z-1
d
1 3 p 4 5 cd 6 7
5 SAM: Z:=Z+V cd c
U:=0 Z? SAM
6 LOOP END cd
B(U),Q(V):=(Z+V)*U p
7 IF B(U)=0 GOTO JOE 2 ELL
Z:=Z-1 d c 12 p p
13 11 10 9 8
8 IF Z=0 GOTO ELL
U:=U+1 YY U,V? U,V? U,Z?
9 UNTIL U=z p
B(U-1):=B(U+1)+Q(V-1)
10 ELL: B(U+Q(V)):=U+V
11 IF U=V GOTO JOE
12 IF U>V THEN U:=Z
13 YY:Z:=U
2 END
Một số định nghĩa

 Gọi PATHS(P) là tập tất cả các đường đi có


thể trong CFG của chương trình P.
 Một đường đi du-path (def-use) cho biến v là
đường đi trong PATHS(P) thỏa mãn
—Tồn tại DEF(v, m) và USE(v, n) sao cho m và n tương ứng
là đỉnh đầu và cuối của đường đi
 Một đường đi dc-path với biến v là một du-
path với các đỉnh đầu DEF(v, m) và USE(v,n)
sao cho không có đỉnh nào ở trên đường đi đó
gán giá trị cho v.
Một số định nghĩa

 Gán toàn cục của biến x ở đỉnh n là DEF(x, n)


và tồn tại một đường đi từ n đến một đỉnh m
nào đó chứa C-use hoặc P-use toàn cục của
x.
 Một C-use toàn cục của x tại đỉnh n là một C-
use của x ở n và x chưa được gán ở đỉnh nào
khác ngoài n
Một số định nghĩa

 Đường đi đơn giản là đường có đỉnh đầu và cuối


không trùng nhau.
 Đường đi không có vòng lặp là đường tất cả các
đỉnh ko trùng nhau.
 Đường đi đầy đủ là đường từ đỉnh vào đến đỉnh
ra của CFG
 Du-path với biến x ở đỉnh n1 là đường đi n1..nk

—n1 có gán toàn cục cho x và
—nk có c-use của x và đường đi này là đơn giản, hoặc
—nk có p-use của x và đường đi này là không có vòng lặp với x.
Ví dụ liên kết def-use
 Liên kết def-use của chương trình dươi đây là
gì?

read (z)
x = 0
y = 0
if (z  0) {
x = sqrt (z)
if (0  x && x  5)
y = f (x)
else
y = h (z)
}
y = g (x, y)
print (y)
Ví dụ liên kết def-use
def-use cho biến z. read (z)
x=0
y=0
if (z  0)
{
x = sqrt (z)
if (0  x && x  5)
y = f (x)
else
y = h (z)
}
y = g (x, y)
print (y)
Ví dụ liên kết def-use
Variable Defined at Used at Comment
locks 9 Declaration
locks 22 READ
locks 23 Predicate use
locks 26 Computation Use
stocks 9 READ
stocks 27 Computation Use
num_locks 26 Assignment
num_locks 26 Computation Use
num_locks 33 WRITE
Tiêu chuẩn bao phủ kiểm thử
DU-Path
 Ý tưởng
—Sử dụng thông tin def-use và tiêu chuẩn cụ thể để nhận
được các đường đi cụ thể trong đồ thị CFG
• Từ đó xác định các ca kiểm thử
 Chúng ta giả sử T là tập các đường đi đầy đủ
và khả thi trong CFG của chương trình P và V
là tập tất cả các biến trong P
Tiêu chuẩn bao phủ DU-Path

 T thỏa mãn tiêu chuẩn All-Defs nếu và chỉ nếu


với mọi v, T chứa các đường đi dc-path từ mọi
đỉnh gán của v đến một đỉnh dùng của v
—Tập đến được của các gán
 T thỏa mãn tiêu chuẩn All-Uses nếu và chỉ nếu
với mọi v, T chứa các đường đi dc-path từ mọi
đỉnh gán của v đến mọi đỉnh dùng v và đến
đỉnh tiếp theo của mỗi USE(v, n)
 Chúng ta có thể làm mịn hơn bằng All-C-Uses
và All-P-Uses
Tiêu chuẩn bao phủ DU-Path

 All-P-Uses/Some-C-Uses
—Với mọi v, T gồm các đường đi dc-path từ mọi đỉnh gán
của v đến mọi đỉnh p-use của v và nếu một định nghĩa
của v không có p-use thì tồn tại một đường đi dc-path
đến ít nhất một c-use
 All-C-Uses/Some-P-Uses
—Với mọi v, T gồm các đường đi dc-path từ mọi đỉnh gán
của v đến mọi đỉnh c-use của v và nếu một định nghĩa
của v không có c-use thì tồn tại một đường đi dc-path
đến ít nhất một p-use
Tiêu chuẩn bao phủ DU-Path

 All-DU-Paths
—Với mọi v, T gồm các đường đi dc-path từ mọi đỉnh gán
của v đến mọi đỉnh dùng của v và đến đỉnh tiếp theo của
mỗi USE(v, n) và các đường đi này hoặc là lặp một lần
hoặc không lặp
Ví dụ All-DU-Paths: pow(x,y)
1. void pow (int x, y) /* pow(x,y) tính x mũ y với x, y là số
2. { nguyên
3. float z;
INPUT: giá trị của x và y.
OUTPUT: in x mũ y ra màn hình.
4. int p;
*/
5. if (y < 0)
6. p = 0 – y;
7. else p = y;
8. z = 1.0;
9. while (p != 0)
10. {
b g
11. z = z * x;
a d f i
12. p = p – 1; 1 5 8 9 14 16 17
13. }
14.if (y < 0) c e h
15. z = 1.0 / z;
16.printf(z);
17.}
All-DU-Paths vơi biến x

1 void pow (int x, y)


2 {
3 float z;
4 int p;
5 if (y < 0)
6 p = 0 – y;
7 else p = y;
8 z = 1.0; b g
9 while (p != 0) a d f i
10 { 1 5 8 9 14 16 17
11 z = z * x;
12 p = p – 1;
13 } c e h
14 if (y < 0)
15 z = 1.0 / z;
16 printf(z);
17 }
All-DU-Paths với biến x

1 void pow (int x, y)


2 {
3 float z;
4 int p;
5 if (y < 0)
6 p = 0 – y;
7 else p = y; b g
8 z = 1.0;
9 while (p != 0) a d f i
10 { 1 5 8 9 14 16 17
11 z = z * x;
12 p = p – 1; c h
13 } e
14 if (y < 0)
15 z = 1.0 / z;
16 printf(z);
17 }
All-DU-Paths với biến y

1 void pow (int x, y)


2 {
3 float z;
4 int p;
5 if (y < 0) b g
6 p = 0 – y; a f i
7 else p = y; d
1 5 8 9 14 16 17
8 z = 1.0;
9 while (p != 0)
10 { c e h
11 z = z * x;
12 p = p – 1;
13 }
14 if (y < 0)
15 z = 1.0 / z;
16 printf(z);
17 }
All-DU-Paths với biến y

1 void pow (int x, y)


2 {
3 float z;
4 int p;
5 if (y < 0) b g
6 p = 0 – y; a f i
7 else p = y; d
1 5 8 9 14 16 17
8 z = 1.0;
9 while (p != 0)
10 { c e h
11 z = z * x;
12 p = p – 1;
13 }
14 if (y < 0)
15 z = 1.0 / z;
16 printf(z);
17 }
All-DU-Paths với biến y

1 void pow (int x, y)


2 {
3 float z;
4 int p;
5 if (y < 0) b g
6 p = 0 – y; a f i
7 else p = y; d
1 5 8 9 14 16 17
8 z = 1.0;
9 while (p != 0)
10 { c e h
11 z = z * x;
12 p = p – 1;
13 }
14 if (y < 0)
15 z = 1.0 / z;
16 printf(z);
17 }
Ví dụ tính trung bình
public static double ReturnAverage(int value[], int AS, int MIN, int MAX) {
int i, ti, tv, sum;
double av;
i = 0; ti = 0; tv = 0; sum = 0;
while (ti < AS && value [i] != -999) {
ti++;
if (value[i] >= MIN && value[i} <= MAX) {
tv++;
sum = sum + value[i];
}
i++;
}
if (tv > 0)
av = (double) sum/tv;
else
av = (double) -999;
return (av)
}
CFG của hàm tính trung bình
Initialize: value[]
1 AS, MIN, MAX

2 i=0; ti=0;
tv=0, sum=0

3 ((ti < AS) &&


(value[i] != -999))
F T

7 ti++;
tv > 0 4 (value[i] >= MIN &&
value[i] <= MAX)
T
F T
F
9 av = (double) sum/tv tv++;
av = (double) -999 sum= sum+value[i]

8 5

10 return(av) i++
6
Đường đi
 c-use toàn cục cho biến tv: đỉnh 9 (tv được
gán ở đỉnh 2 và 5)
 Các đường đi def-clear cho biến tv: 2-3-4-5,
2-3-4-6
 Đường đi đơn giản: 2-3-4-5 và 3-4-6-3
 Đường đi thỏa mãn All-defs cho biến tv:
—1-2-3-4-5-6-3-7-9-10,
—Và với p-uses 1-2-3-7-8-10 và 1-2-3-4-5-6-3-7-9-10
Đường đi

 Đường đi cho tiêu chuẩn All-c-uses cho biến


ti:
—1-2-3-4-5-6-3-7-8-10,
—1-2-3-4-5-6-3-7-9-10,
—1-2-3-4-6-3-7-8-10,
—1-2-3-4-6-3-7-9-10
 Đường đi cho tiêu chuẩn All-p-uses cho biến
tv:
—1-2-3-7-8-10
—1-2-3-7-9-10
—1-2-3-4-5-6-3-7-8-10
—1-2-3-4-5-6-3-7-9-10
Đường đi

 All-p-uses/some-c-uses cho i:
—1-2-3-4-5-6-3-7-9-10
 All-c-uses/some-p-uses cho AS:
—1-2-3-4-5-6-3-7-9-10
 All-uses:
—Hợp của all-c-uses và all-p-uses
 All-du-paths choh tv:
—1-2-3-4-5-6-3-7-8-10 …. 1-2-3-7-9-10
Tổng kết

 Nên kết hợp áp dụng cả kiểm thử hộp đen và hộp


trắng
 Các phương pháp kiểm thử hộp đen có thể bao
phủ đường đi tốt nhưng thường có nhiều dư thừa
 Liệu chúng ta có thể có một độ đo để so sánh
mức độ hiệu quả của một kỹ thuật hộp đen với
một kỹ thuật hộp trắng?
—Các phương pháp hộp đen được đo trên số ca kiểm thử tạo
ra
—Các phương pháp hộp trắng được đo trên mức độ bao phủ
đường đi chúng đạt được
Bài tập

 Áp dụng các phương pháp thiết kế ca kiểm


thử đã học vào các chương trình được giao
viết ở chương 1.

55

You might also like