Kiểm thử dựa trên luồng dữ liệu

Download Report

Transcript Kiểm thử dựa trên luồng dữ liệu

Kiểm thử và đảm bảo chất
lượng phần mềm
Kiểm thử luồng dữ liệu
Nội dung
• Kiểm thử cấu trúc
– Tổng quan
– Kiểm thử theo luồng điều khiển
– Kiểm thử theo luồng dữ liệu
– Phương pháp kết hợp
– Tổng kết về kiểm thử cấu trúc
2
Ý 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-Cuses, 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
3
4
5
6
7
8
9
10
11
12
13
2
INPUT X,Y
Z:= X+Y
Y:= X-Y
IF Z>=0 GOTO SAM
JOE: Z:=Z-1
SAM: Z:=Z+V
U:=0
LOOP
B(U),Q(V):=(Z+V)*U
IF B(U)=0 GOTO JOE
Z:=Z-1
IF Z=0 GOTO ELL
U:=U+1
UNTIL U=z
B(U-1):=B(U+1)+Q(V-1)
ELL: B(U+Q(V)):=U+V
IF U=V GOTO JOE
IF U>V THEN U:=Z
YY:Z:=U
END
1
3
p
JOE
4
Z?
END
2
d
p
d
13
YY
c 12
U,V?
LOOP
cd
5 cd
SAM
ELL
11
U,V?
10
6
B(U)?
7
c
cd
p
p
9
U,Z?
p
8
p
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 Cuse 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 mà
– 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
stocks
num_locks
READ
27
26
Computation Use
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)
2. {
3. float z;
4. int p;
5. if (y < 0)
6.
p = 0 – y;
7. else p = y;
8. z = 1.0;
9. while (p != 0)
10.
{
11.
z = z * x;
12.
p = p – 1;
13.
}
14.if (y < 0)
15.
z = 1.0 / z;
16.printf(z);
17.}
/* pow(x,y) tính x mũ y với x, y là số nguyên
INPUT: giá trị của x và y.
OUTPUT: in x mũ y ra màn hình.
*/
b
1
a
5
g
8
c
d
9
f
e
14
16
h
i
17
All-DU-Paths vơi biến x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void pow (int x, y)
{
float z;
int p;
if (y < 0)
p = 0 – y;
else p = y;
z = 1.0;
while (p != 0)
a
{
1
z = z * x;
p = p – 1;
}
if (y < 0)
z = 1.0 / z;
printf(z);
}
b
5
g
8
c
d
9
f
e
14
16
h
i
17
All-DU-Paths với biến x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void pow (int x, y)
{
float z;
int p;
if (y < 0)
p = 0 – y;
else p = y;
z = 1.0;
while (p != 0)
1
{
z = z * x;
p = p – 1;
}
if (y < 0)
z = 1.0 / z;
printf(z);
}
b
a
5
g
8
c
d
9
f
e
14
16
h
i
17
All-DU-Paths với biến y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void pow (int x, y)
{
float z;
int p;
if (y < 0)
p = 0 – y;
else p = y;
z = 1.0;
while (p != 0)
{
z = z * x;
p = p – 1;
}
if (y < 0)
z = 1.0 / z;
printf(z);
}
b
1
a
5
g
8
c
d
9
f
e
14
16
h
i
17
All-DU-Paths với biến y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void pow (int x, y)
{
float z;
int p;
if (y < 0)
p = 0 – y;
else p = y;
z = 1.0;
while (p != 0)
{
z = z * x;
p = p – 1;
}
if (y < 0)
z = 1.0 / z;
printf(z);
}
b
1
a
5
g
8
c
d
9
f
e
14
16
h
i
17
All-DU-Paths với biến y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void pow (int x, y)
{
float z;
int p;
if (y < 0)
p = 0 – y;
else p = y;
z = 1.0;
while (p != 0)
{
z = z * x;
p = p – 1;
}
if (y < 0)
z = 1.0 / z;
printf(z);
}
b
1
a
5
g
8
c
d
9
f
e
14
16
h
i
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
1
2
3
Initialize: value[]
AS, MIN, MAX
i=0; ti=0;
tv=0, sum=0
((ti < AS) &&
(value[i] != -999))
T
F
ti++;
4 (value[i] >= MIN &&
value[i] <= MAX)
7
tv > 0
T
F
T
F
av = (double) -999
9
av = (double) sum/tv
tv++;
sum= sum+value[i]
5
8
10
return(av)
6
i++
Đườ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-79-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