You are on page 1of 44

Kiểm Thử Luồng Dữ liệu

Khoa CNTT – Trường ĐHCN - ĐHQGHN


Nội dung
• Giới thiệu
• Kiểm thử dòng dữ liệu tĩnh
• Kiểm thử dòng dữ liệu động
• Một số khái niệm
• Các độ đo cho kiểm thử dòng dữ liệu
Giới thiệu
• Biến x được sử dụng nhưng không
#include <stdio.h> được khởi tạo giá trị
• Biến y được khởi tạo nhưng không được
void main() {
sử dụng trong chương trình
int x;
if(x == 5){ à Làm sao để phát hiện được các lỗi này?
int y = 10;
}
}
Giới thiệu

vKiểm thử dòng dữ liệu giúp phát hiện các lỗi liên quan đến việc
gán và sử dụng các biến trong chương trình

vKiểm thử dòng dữ liệu chia thành 2 cấp độ


- Kiểm thử dòng dữ liệu tĩnh (static data flow testing)
- Kiểm thử dòng dữ liệu động (dynamic data flow testing)
Gán giá trị cho biến - Variable definition

Một biến trong chương trình được gán (defined) khi biến đó xuất hiện:
• ở vế trái (left hand side) của một biểu thức gán (assignment statement)
vd: y = 10
• ở trong input statement
vd: read(y)
• call-by-reference parameter
vd: update(x, &y)
Sử dụng giá trị của biến – Variable use

Một biến trong chương trình được sử dụng (used) khi nó xuất hiện:

• ở vế phải (right hand side) của một biểu thức gán (assignment statement)
vd: y = x + 17
• call-by-value parameter
vd: y = sqrt(x)
• in the predicate of a brach statement
vd: if(x > 0){…}
Variable use

Một biến có thể được used sau đó re-defined trong cùng 1 câu lệnh,
khi nó xuất hiện:
• ở trong cả 2 vế của biểu thứ gán
vd: y = y + x
• call-by-reference parameter
vd: update(&y)
Kiểm thử dòng dữ liệu tĩnh
Kiểm thử dòng dữ liệu động
Kiểm thử dòng dữ liệu tĩnh – Static data flow testing

• Kiểm thử dòng dữ liệu tĩnh: Phân tích mã nguồn mà không chạy
chương trình nhằm phát hiện các bất thường

• Một số vấn đề phổ biến về dòng dữ liệu


ØGán giá trị rồi gán tiếp giá trị
ví dụ 2 câu lệnh tuần tự: x = f1(); x = f2();
ØChưa gán giá trị nhưng được sử dụng
ØĐã được khai báo và gán giá trị nhưng không được sử dụng
Kiểm thử dòng dữ liệu động – Dynamic data flow testing

• Lý do cần thực hiện kiểm thử dòng dữ liệu động


• Kiểm thử dữ liệu tĩnh không đảm bảo phát hiện được tất cả các lỗi liên quan đến khởi tạo,
gán giá trị mới và sử dụng các biến
• Có thể xem là 1 bước tiền xử lý
• Cần đảm bảo giá trị của biến có được gán đúng (correctly)
• Đảm bảo sự đúng đắn của các giá trị được sinh ra trong quá trình tính toán

• Quy trình tổng quát của kiểm thử dòng dữ liệu động:
- Vẽ đồ thị luồng điều khiển (CFG)
- Lựa chọn tiêu chí kiểm thử luồng dữ liệu
- Xác định các đường đi trên CFG thoả mãn tiêu chí kiểm thử đã chọn
- Sinh các ca kiểm thử tương ứng
Một số khái niệm
• Def: Một câu lệnh thực hiện việc gán giá trị cho một biến được gọi là câu lệnh
def của biến
vd: y = 10; là câu lệnh def của biến y
• Use: Một câu lệnh sử dụng một biến được gọi là câu lệnh use của biến
vd: x = y; là câu lệnh def của biến x, và là câu lệnh use của biến y
• P-use (predicate-use): câu lệnh sử dụng một biến trong biểu thức điều kiện
vd: if(x == 0) là câu lệnh p-use của biến x
• C-use (computation-use): các câu lệnh use còn lại
vd: x = y; là câu lệnh c-use của biến y
print(y): là câu lệnh c-use của biến y
Ví dụ
1. Input(A, B){
Xác định def, p-use, c-use của các biến trong
2. if(B > 1){ chương trình?
3. A = A + 7; def(A) = {1, 3}
} p-use(A) = {4}
c-use(A) = {3, 5, 6}
4. if(A > 10){
5. B = A + B;
} def(B) = {1, 5}
p-use(B) = {2}
6 output(A, B); c-use(B) = {5, 6}
7 }
Ví dụ
1. Input(A, B){ 1. Input(A, B)
2. if(B > 1){
3. A = A + 7;
} 2. If(B > 1)

4. if(A > 10){


T F
5. B = A + B;
}
3. A = A + 7 4. if(A >10)
6 output(A, B)
T F
}
5.B = A + B 6. Output(A, B)

Exit
Một số khái niệm

• Đường đi (Path): Tất cả các đường đi có thể trong CFG của chương trình

• Def-clear path: Một đường đi (i, 𝑛!,…,𝑛" ) được gọi là def-clear path của biến v
từ i đến 𝑛" nếu v được định nghĩa tại i, các đỉnh 𝑛!,…, 𝑛" không chứa câu lệnh
def của v
vd: def-clear path của biến A: (1, 2(F), 4)

• Complete path: là đường đi bắt đầu từ node Entry và kết thúc ở node Exit
Ví dụ
1. Input(A, B)
• (1, 2, 4, 5) là def-clear path từ đỉnh
1 tới đỉnh 5 của biến A
2. If(B > 1)
+ A không được re-defined trên
đường đi này
T F
• (1, 2, 3, 4, 5) không là một def-
clear path từ đỉnh 1 tới đỉnh 5 của 4. if(A >10)
3. A = A + 7
biến A
T F
+ A được re-defined tại
đỉnh 3 trên đường đi này 5.B = A + B 6. Output(A, B)

Exit
Một số khái niệm

Du-pair (Def-use pair): (d,u) là cặp def-use của biến v nếu:


§ d là đỉnh tương ứng với câu lệnh def của v
§ u là đỉnh tương ứng với câu lệnh use của v
§ Tồn tại ít nhất một def-clear path của biến v từ d tới u
Xác định du-pair của biến A entry

Du-pair path 1. Input(A, B)


(1, 3) <1, 2(T), 3>
(1, 4) <1, 2(F) , 4>
(1, 5) <1, 2(F), 4(T), 5> 2. If(B > 1)
(1,6) <1, 2(F), 4(T), 5, 6>
T F
<1, 2(F), 4(F), 6>
(3,4) <3,4>
3. A = A + 7 4. if(A >10)
(3,5) <3, 4(T), 5>
(3, 6) <3, 4(T), 5, 6> T F
(3, 6) <3, 4(F), 6>
5.B = A + B 6. Output(A, B)

Exit
Xác định du-pair của biến A entry

Du-pair path 1. Input(A, B)


(1, 3) <1, 2(T), 3>
(1, 4) <1, 2(F) , 4>
(1, 5) <1, 2(F), 4(T), 5> 2. If(B > 1)
(1,6) <1, 2(F), 4(T), 5, 6>
T F
<1, 2(F), 4(F), 6>
(3,4) <3,4>
3. A = A + 7 4. if(A >10)
(3,5) <3, 4(T), 5>
(3, 6) <3, 4(T), 5, 6> T F
(3, 6) <3, 4(F), 6>
5.B = A + B 6. Output(A, B)

Exit
Xác định du-pair của biến A entry

Du-pair path 1. Input(A, B)


(1, 3) <1, 2(T), 3>
(1, 4) <1, 2(F) , 4>
(1, 5) <1, 2(F), 4(T), 5> 2. If(B > 1)
(1,6) <1, 2(F), 4(T), 5, 6>
T F
<1, 2(F), 4(F), 6>
(3,4) <3,4>
3. A = A + 7 4. if(A >10)
(3,5) <3, 4(T), 5>
(3, 6) <3, 4(T), 5, 6> T F
(3, 6) <3, 4(F), 6>
5.B = A + B 6. Output(A, B)

Exit
Các độ đo cho kiểm thử dòng dữ liệu
• All-def coverage
• All-c-uses coverage
• All-c-uses/some-p-uses coverage
• All-p-uses coverage
• All-p-uses/some-c-uses coverage
• All-uses coverage
• All-du-paths coverage
Ví dụ

Xác định def, c-use, p-use của các biến


trong chương trình?

- Biến x: def(x) = {1, 6}


c-use(x) = {3, 6, 7}
p-use(x) = {2, 4, 5}

- Biến a: def(a) = {3, 7}


c-use(a) = {8}
p-use(a) = {}
All-defs coverage

Với mỗi biến v của chương trình, ít nhất 1 def-clear path từ mọi câu
lệnh def của v tới ít nhất một câu lệnh use của v được kiểm thử
All-defs coverage – Ví dụ
- Biến x: def(x) = {1, 6}
c-use(x) = {3, 6, 7}
p-use(x) = {2, 4, 5}
- Biến a: def(a) = {3, 7}
c-use(a) = {8}
p-use(a) = {}

Variable Du-pair Def-clear path Complete path

x (1, 3) 1, 2(T), 3 1, 2(T), 3, 4 (F), 8


(6,6) 6, 5(T), 6 1, 2(F), 4(T), 5(T), 6,
5(T),6, 5(F) 7, 8
a (3,8) 3, 4(F), 8 1, 2(T), 3, 4(F), 8

(7,8) 7, 8 1, 2(F), 4(T), 5(T), 6,


5(T),6, 5(F) 7, 8
All-c-uses coverage

Với mỗi biến v của chương trình, ít nhất 1 def-clear path từ mọi câu
lệnh def của v tới mọi câu lệnh c-use của v được kiểm thử
All-c-uses coverage – Ví dụ
- Biến x: def(x) = {1, 6} c-use(x) = {3, 6, 7} p-use(x) = {2, 4, 5}
- Biến a: def(a) = {3, 7} c-use(a) = {8} p-use(a) = {}

Variable Du-pair Def-clear path Complete path

x (1,3) 1, 2(T), 3 1, 2(T), 3, 4 (F), 8

(1,6) 1, 2(F), 4(T), 5(T), 6 1, 2(F), 4(T), 5(T),


6,5(T),6, 5(F), 7, 8
(1,7) 1, 2(F), 4(T), 5(F), 7 1, 2(F), 4(T), 5(F), 7, 8

(6,6) 6, 5(T), 6 1, 2(F), 4(T), 5(T),


6,5(T),6, 5(F), 7, 8
(6,7) 6, 5(F), 7 1, 2(F), 4(T), 5(T),
6,5(T),6, 5(F), 7, 8

a (3,8) 3, 4(F), 8 1, 2(T), 3, 4(F), 8

(7,8) 7, 8 1, 2(F), 4(T), 5(T),


6,5(T),6, 5(F), 7, 8
All-p-uses coverage

Với mỗi biến v của chương trình, ít nhất 1 def-clear path từ mọi câu
lệnh def của v tới mọi câu lệnh p-use của v được kiểm thử
All-p-uses coverage – Ví dụ
- Biến x: def(x) = {1, 6} c-use(x) = {3, 6, 7} p-use(x) = {2, 4, 5}
- Biến a: def(a) = {3, 7} c-use(a) = {8} p-use(a) = {}

Variable Du-pair Def-clear path Complete path

x (1,2(T)) 1, 2(T) 1, 2(T), 3, 4 (F), 8


(1,2(F)) 1, 2(F) 1, 2(F), 4(T), 5(T), 6, 5(T), 6,
5(F), 7, 8
(1, 4(T)) 1, 2(F), 4(T) 1, 2(F), 4(T), 5(T), 6, 5(T), 6,
5(F), 7, 8
(1, 4(F)) 1, 2(T), 3, 4(F) 1, 2(T), 3, 4(F), 8

(1, 5(T)) 1, 2(F), 4(T), 1, 2(F), 4(T), 5(T), 6, 5(T), 6,


5(T) 5(F), 7, 8

(1, 5(F)) 1, 2(F), 4(T), 1, 2(F), 4(T), 5(F), 7, 8


5(F)
(6, 5(T)) 6, 5(T) 1, 2(F), 4(T), 5(T), 6, 5(T), 6,
5(F), 7, 8

(6, 5(F)) 6, 5(F) 1, 2(F), 4(T), 5(T), 6, 5(T), 6,


5(F), 7, 8
All-c-uses/Some-p-uses coverage

Với mỗi biến v của chương trình, ít nhất 1 def-clear path từ mọi câu
lệnh def của v tới mọi câu lệnh c-use của v được kiểm thử. Nếu trong
chương trình tương ứng với câu lệnh def không có câu lệnh c-use
nào, thì ít nhất 1 def-clear path từ mọi câu lệnh def của v tới ít nhất
một câu lệnh p-use của v được kiểm thử.
All-c-uses/Some-p-uses coverage – Ví dụ
- Biến x: def(x) = {1, 6} c-use(x) = {3, 6, 7} p-use(x) = {2, 4, 5}
- Biến a: def(a) = {3, 7} c-use(a) = {8} p-use(a) = {}

Variable Du-pair Def-clear path Complete path

x (1,3) 1, 2(T), 3 1, 2(T), 3, 4 (F), 8

(1,6) 1, 2(F), 4(T), 5(T), 6 1, 2(F), 4(T), 5(T), 6,


5(T), 6, 5(F), 7, 8
(1,7) 1, 2(F), 4(T), 5(F), 7 1, 2(F), 4(T), 5(F), 7, 8

(6,6) 6, 5(T), 6 1, 2(F), 4(T), 5(T), 6,


5(T), 6, 5(F), 7, 8
(6,7) 6, 5(F), 7 1, 2(F), 4(T), 5(T), 6,
5(T), 6, 5(F), 7, 8

a (3,8) 3, 4(F), 8 1, 2(T), 3, 4(F), 8

(7,8) 7, 8 1, 2(F), 4(T), 5(T), 6,


5(T), 6, 5(F), 7, 8
All-p-uses/Some-c-uses Coverage

Với mỗi biến v của chương trình, ít nhất 1 def-clear path từ mọi câu
lệnh def của v tới mọi câu lệnh p-use của v được kiểm thử. Nếu trong
chương trình tương ứng với câu lệnh def không có câu lệnh p-use
nào, thì ít nhất 1 def-clear path từ mọi câu lệnh def của v tới ít nhất
một câu lệnh c-use của v được kiểm thử.
All-p-uses/Some-c-uses– Ví dụ
- Biến x: def(x) = {1, 6} c-use(x) = {3, 6, 7} p-use(x) = {2, 4, 5}
- Biến a: def(a) = {3, 7} c-use(a) = {8} p-use(a) = {}

Variabl Du-pair Def-clear path Complete path


e
x (1,2(T)) 1, 2(T) 1, 2(T), 3, 4 (F), 8
(1,2(F)) 1, 2(F) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8

(1, 4(T)) 1, 2(F), 4(T) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8


(1, 4(F)) 1, 2(T), 3, 4(F) 1, 2(T), 3, 4(F), 8

(1, 5(T)) 1, 2(F), 4(T), 5(T) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(1, 5(F)) 1, 2(F), 4(T), 5(F) 1, 2(F), 4(T), 5(F), 7, 8
(6, 5(T)) 6, 5(T) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(6, 5(F)) 6, 5(F) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
a (3, 8) 3, 4(F), 8 1, 2(T), 3, 4(F), 8
(7, 8) 7,8 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
All-uses coverage

Với mỗi biến v của chương trình, ít nhất 1 def-clear path từ mọi câu
lệnh def của v tới mọi câu lệnh c-use và p-use của v được kiểm kiểm
thử
All-uses coverage – Ví dụ
- Biến x: def(x) = {1, 6} c-use(x) = {3, 6, 7} p-use(x) = {2, 4, 5}
- Biến a: def(a) = {3, 7} c-use(a) = {8} p-use(a) = {}
Variable Du-pair Def-clear path Complete path
x (1,2(T)) 1, 2(T) 1, 2(T), 3, 4 (F), 8
(1,2(F)) 1, 2(F) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(1, 3) 1, 2(T), 3 1, 2(T), 3, 4 (F), 8
(1, 4(T)) 1, 2(F), 4(T) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(1, 4(F)) 1, 2(T), 3, 4(F) 1, 2(T), 3, 4(F), 8
(1, 5(T)) 1, 2(F), 4(T), 5(T) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(1, 5(F)) 1, 2(F), 4(T), 5(F) 1, 2(F), 4(T), 5(F), 7, 8
(1,6) 1, 2(F), 4(T), 5(T), 6 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(1,7) 1, 2(F), 4(T), 5(F), 7 1, 2(F), 4(T), 5(F), 7, 8
(6, 5(T)) 6, 5(T) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(6, 5(F)) 6, 5(F) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(6,6) 6, 5(T), 6 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(6,7) 6, 5(F), 7 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
a (3, 8) 3, 4(F), 8 1, 2(T), 3, 4(F), 8
(7, 8) 7,8 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
All-Du-pairs coverage

Với mỗi biến v của chương trình, tất cả du-paths của v được kiểm
thử. Nếu nó có nhiều hơn 1 đường đi giữa 2 câu lệnh def và use của
1 biến, cần kiểm thử tất cả các đường đi đó.
All-du-pair coverage– Ví dụ
- Biến x: def(x) = {1, 6} c-use(x) = {3, 6, 7} p-use(x) = {2, 4, 5}
- Biến a: def(a) = {3, 7} c-use(a) = {8} p-use(a) = {}
Variable Du-pair Def-clear path Complete path
x (1,2(T)) 1, 2(T) 1, 2(T), 3, 4 (F), 8
(1,2(F)) 1, 2(F) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(1, 3) 1, 2(T), 3 1, 2(T), 3, 4 (F), 8
(1, 4(T)) 1, 2(F), 4(T) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(1, 4(T)) 1, 2(T), 3, 4(T) 1, 2(T), 3, 4 (T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(1, 4(F)) 1, 2(T), 3, 4(F) 1, 2(T), 3, 4(F), 8
(1, 5(T)) 1, 2(F), 4(T), 5(T) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(1, 5(F)) 1, 2(F), 4(T), 5(F) 1, 2(F), 4(T), 5(F), 7, 8
(1,6) 1, 2(F), 4(T), 5(T), 6 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(1,7) 1, 2(F), 4(T), 5(F), 7 1, 2(F), 4(T), 5(F), 7, 8
(6, 5(T)) 6, 5(T) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
(6, 5(F)) 6, 5(F) 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
Path (1, 2(T), 3, 4 (T), 5(T), 6, 5(T), 6, 5(F), 7, 8) is an
(6,6) 6, 5(T), 6 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
infeasible path
(6,7) 6, 5(F), 7 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
a (3, 8) 3, 4(F), 8 1, 2(T), 3, 4(F), 8
(7, 8) 7,8 1, 2(F), 4(T), 5(T), 6, 5(T), 6, 5(F), 7, 8
Mối quan hệ giữa các độ đo cho kiểm thử dòng dữ liệu
Tổng kết
• Kiểm thử dòng dữ liệu:
- kiểm thử dòng dữ liệu tĩnh
- kiểm thử dòng dữ liệu tĩnh
• Các khái niệm: def, use (c-use, p-use), def-clear path, du-pair
• Các độ đo cho kiểm thử dòng dữ liệu
Bài tập
Bài 1
Bài 2:

Cho đoạn mã nguồn sau, hãy:


1. Vẽ đồ thị dòng điều khiển (CFG)
2. Xác định các du-pairs cho biến X và Y
3. Sinh đường đi và các ca kiểm thử với độ đo all-use
Bài 3
Bài 4
Bài 5
Cho đoạn mã nguồn như hình bên,

1. Xây dựng CFG cho hàm UCLN với


đồ thị C2
2. Sinh đường đi và các ca kiểm thử
với độ đo C2
3. Sinh đường đi và các ca kiểm thử
với độ đo all-def coverage
Bài 6

• Kiểm thử chương trình của bạn với độ phủ all-uses

You might also like