Tải bản đầy đủ (.pdf) (59 trang)

XÂY DỰNG CÔNG cụ KIỂM THỬ tự ĐỘNG CHO các CHƯƠNG TRÌNH c

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.99 MB, 59 trang )

ĐẠI HỌC QUỐC GIA HÀ NỘI
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ

Nguyễn Đức Anh

XÂY DỰNG CÔNG CỤ KIỂM THỬ TỰ ĐỘNG CHO
CÁC CHƯƠNG TRÌNH C

KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY
Ngành: Công nghệ thông tin

HÀ NỘI – 2015


ĐẠI HỌC QUỐC GIA HÀ NỘI
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ

Nguyễn Đức Anh

XÂY DỰNG CÔNG CỤ KIỂM THỬ TỰ ĐỘNG CHO
CÁC CHƯƠNG TRÌNH C

KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY
Ngành: Công Nghệ Thông Tin

Cán bộ hướng dẫn: TS. Phạm Ngọc Hùng
(ký tên)

HÀ NỘI - 2015



VIETNAM NATIONAL UNIVERSITY, HANOI
UNIVERSITY OF ENGINEERING AND TECHNOLOGY

Nguyen Duc Anh

A METHOD AND TOOL SUPPORTING FOR
AUTOMATED TESTING OF C PROGRAMS

THE BS THESIS
Major: Information Technology

Supervisor: Dr. Pham Ngoc Hung

LỜI CẢM ƠN

HA NOI - 2015


LỜI CẢM ƠN

Đầu tiên, tôi xin gửi lời cám ơn chân thành tới Tiến sĩ Phạm Ngọc Hùng – giảng
viên bộ môn Công Nghệ Phần Mềm – người đã hướng dẫn tận tình, tỉ mỉ, chu đáo tôi
trong suốt hai năm làm khóa luận tốt nghiệp. Quãng thời gian được thầy hướng dẫn đã
giúp tôi học hỏi, đúc kết được nhiều kinh nghiệm về phương pháp nghiên cứu, kĩ năng
giao tiếp, kĩ năng làm việc nhóm, kĩ năng trình bày. Thầy còn truyền cho tôi ngọn lửa yêu
nghiên cứu khoa học, niềm tin vượt qua những khó khăn trong cuộc sống và dạy tôi cách
vượt qua những khó khăn đó. Tôi cảm thấy tự hào và may mắn khi là một sinh viên được
thầy hướng dẫn trong những năm tháng đại học.
Ngoài ra, tôi xin gửi lời cám ơn chân thành đến tập thể lớp K56 đã giúp đỡ tôi nhiệt
tình để hoàn thành khóa luận sao cho đạt hiệu quả cao nhất. Các bạn đã giúp đỡ tôi bằng

hành động, bằng lời nói mỗi khi tôi gặp khó khăn, thất bại. Bốn năm bên nhau không phải
là dài nhưng đối với tôi, đây là quãng thời gian tuyệt vời nhất và không thể nào quên.
Tiếp theo, tôi xin gửi lời cảm ơn đến các thầy cô giảng viên Trường Đại học Công
Nghệ - Đại học Quốc Gia Hà Nội – những người đã tận tâm truyền đạt những kiến thức
quý báu làm nền tảng để tôi tiếp tục đi xa hơn nữa trong lĩnh vực công nghệ thông tin.
Cuối cùng, tôi xin được cảm ơn gia đình đã nuôi tôi khôn lớn để trở thành người có
ích cho xã hội, giúp tôi có một điểm tựa vững chắc để yên tâm học hành trong suốt bao
năm qua. Tôi xin gửi lời cám ơn chân thành tới cha, mẹ, em gái đã luôn động viên và cổ
vũ tôi mỗi khi tôi gặp khó khăn và thử thách.
Hà Nội, ngày 03 tháng 05 năm 2014
Sinh viên

Nguyễn Đức Anh


TÓM TẮT

Ngày nay, ngôn ngữ C là một trong những ngôn ngữ lập trình phổ biến để phát triển phần
mềm, đặc biệt là các phần mềm hệ thống. Một trong những kĩ thuật kiểm thử hiệu quả hay được
sử dụng là sinh ca kiểm thử trong kiểm thử hộp trắng dòng điều khiển. Để tiết kiệm chi phí kiểm
thử phần mềm, quá trình sinh ca kiểm thử nên được tự động hóa hết mức có thể. Trong khi đó,
các công cụ kiểm thử hiện nay chỉ tập trung vào thực thi các ca kiểm thử mà ít quan tâm đến sinh
ca kiểm thử tự động. Một vài công cụ kiểm thử sinh ca kiểm thử tự động nhưng số lượng ca kiểm
thử không xác định hoặc khá lớn gây khó khăn cho quản lý, ngoài ra còn hạn chế về thời gian
sinh ca kiểm thử.
Vì thế, khóa luận đề xuất một phương pháp sinh ca kiểm thử tự động cho một hàm C chứa
các biến số nguyên, số thực và biến mảng sử dụng kĩ thuật kiểm thử hộp trắng dòng điều khiển
theo hướng tĩnh và cài đặt công cụ hỗ trợ CFT4CUnit. Đầu vào gồm một hàm C và tiêu chí phủ
kiểm thử phủ. Đầu ra gồm tập ca kiểm thử thỏa mãn tiêu chí phủ kiểm thử và tập ca kiểm thử để
kiểm thử vòng lặp (nếu hàm C có vòng lặp). Cụ thể bước đầu tiên, mã nguồn được phân tích để

sinh đồ thị dòng điều khiển thỏa mãn tiêu chí phủ kiểm thử. Sau đó, đồ thị dòng điều khiển được
phân tích để xây dựng tập đường kiểm thử. Tiếp theo, các đường kiểm thử chứa vòng lặp được
cấu trúc lại để sinh thêm các đường kiểm thử mới dùng kiểm thử tính đúng đắn vòng lặp. Kế tiếp,
các đường kiểm thử được phân tích bằng kĩ thuật SE để xây dựng hệ ràng buộc tương ứng. Cuối
cùng, hệ ràng buộc được giải để sinh ca kiểm thử bằng cách kết hợp kĩ thuật sinh ngẫu nhiên và
tận dụng thế mạnh các công cụ SMT-Solver. Kết quả thực nghiệm cho thấy khả năng phát hiện
được lỗi khá tốt trong hàm C với số bộ ca kiểm thử tối thiểu mà vẫn đảm bảo tính đúng đắn cao
của mã nguồn. Ngoài ra, thời gian sinh ca kiểm thử được cải thiện đáng kể và giải được nhiều hệ
ràng buộc khác nhau vì kết hợp kĩ thuật sinh ngẫu nhiên và sử dụng công cụ SMT-Solver.
Từ khóa: Kiểm thử tự động, hàm C, đồ thị dòng điều khiển, ca kiểm thử, Symbolic Execution,
SMT-Solver


ABSTRACT

Nowadays, C programming language has been known as one of the most popular
programming languages to develope applications, especially system applications. Because of
high demand in quality, testing phase is performed quite rigorously and strictly. As a result, the
cost of the testing phase can be up to 40% - 60% the total cost of application development
process.
Test case generation in white-box testing is an effective technique and used widely to
ensure the high quality of applications. To reduce the cost of the testing phase, the test case
generation process should be automated as much as possible. However, some testing tools focus
on executing test cases and output the testing report instead of generating test cases
automatically. Other testing tools assist to generate test cases automatically but the number of test
cases may be a lot or un-known which cause many difficult and challenging problems such as
management, time limit, etc.
The thesis proposes an approach how to generate test cases automatically for C Unit
containing integer variables, float variables, array variables. The proposed approach is based on
white-box testing and implements in CFT4CUnit tool to demonstrate the effectiveness of the

approach. Firstly, source code is analysed to generate corresponding Control Flow Graph (CFG).
Then I traverse the CFG to obtain the independent paths. After that, paths containing loop is reconstructed to create some new paths used to test the loop. Next, each path is analysed by using
symbolic execution technique to generate corresponding constraints. Finally, the process of
solving the constraints is performed to find solution as fast as possible by combining random
technique and SMT-Solvers. The experimental result shows the effectiveness of the approach
with the minimum number of test cases but ensures the high quality of source code.
Keywords: automated testing, C Unit, control flow testing, test case, symbolic execution, SMTSolver


LỜI CAM ĐOAN

Tôi xin cam đoan rằng những nghiên cứu về kiểm thử tự động cho hàm C được trình
bày trong luận án này là của tôi và chưa từng được nộp như một báo cáo khóa luận tại
trường Đại học Công Nghệ - Đại học Quốc Gia Hà Nội hoặc bất kỳ trường đại học khác.
Những gì tôi viết ra không sao chép từ các tài liệu, không sử dụng các kết quả của người
khác mà không trích dẫn cụ thể.
Tôi xin cam đoan công cụ kiểm thử tự động tôi trình bày trong khoá luận là do tôi tự
phát triển, không sao chép mã nguồn của người khác. Nếu sai tôi hoàn toàn chịu trách
nhiệm theo quy định của trường Đại học Công Nghệ - Đại học Quốc Gia Hà Nội.

Hà Nội, ngày 03 tháng 05 năm 2015
Sinh viên

Nguyễn Đức Anh


MỤC LỤC
Chương 1.

Đặt vấn đề ................................................................................................................. 1


Chương 2.

Tổng quan kĩ thuật kiểm thử hộp trắng dòng điều khiển.................................... 4

2.1. Tổng quan kĩ thuật kiểm thử hộp trắng dòng điều khiển ......................................... 4
2.2. Quy trình chung của kiểm thử hộp trắng dòng điều khiển theo hướng động .......... 4
2.3. Quy trình chung của kiểm thử hộp trắng dòng điều khiển theo hướng tĩnh ............ 6
2.3.1. Các tiêu chí phủ kiểm thử .................................................................................. 7
2.3.2. Đồ thị dòng điều khiển ...................................................................................... 8
2.3.3. Đường kiểm thử ................................................................................................. 9
2.4. So sánh kĩ thuật kiểm thử hộp trắng dòng điều khiển theo hướng tĩnh và động ... 10
2.5. Tầm quan trọng của tự động hóa quy trình kiểm thử hộp trắng dòng điều khiển . 11
Chương 3. Phương pháp kiểm thử tự động hàm C sử dụng kĩ thuật kiểm thử hộp trắng
dòng điều khiển theo hướng tĩnh................................................................................................ 12

3.1. Tổng quan phương pháp kiểm thử hộp trắng dòng điều khiển theo hướng tĩnh..... 12
3.2. Sinh đồ thị dòng điều khiển từ mã nguồn .............................................................. 13
3.3. Xây dựng tập đường kiểm thử từ đồ thị dòng điều khiển ...................................... 16
3.3.1. Xây dựng tập đường đi độc lập........................................................................ 16
3.3.2. Xây dựng đường kiểm thử vòng lặp ................................................................ 17
3.3.2.1. Kiểm thử đường đi chứa vòng lặp đơn ..................................................... 18
3.3.2.2. Kiểm thử đường đi chứa hai vòng lặp lồng nhau .................................... 19
3.4. Sinh tập dữ liệu kiểm thử từ tập đường kiểm thử .................................................. 20
3.4.1. Xây dựng hệ ràng buộc .................................................................................... 20
3.4.2. Tìm nghiệm thỏa mãn hệ ràng buộc ................................................................ 22
3.4.2.1. Giải hệ sử dụng kĩ thuật sinh ngẫu nhiên ................................................ 22


3.4.2.2. Giải hệ sử dụng SMT-Solver ................................................................... 23

3.4.2.3. So sánh ưu điểm, nhược điểm của hai hướng sinh ca kiểm thử .............. 29
Chương 4.

Thực nghiệm .......................................................................................................... 31

4.1. Các thư viện hỗ trợ ................................................................................................. 31
4.1.1. Giới thiệu về thư viện SMT-Solver SmtInterpol ............................................. 31
4.1.2. Giới thiệu về thư viện CDT ............................................................................. 31
4.1.3. Giới thiệu về thư viện Jeval ............................................................................. 32
4.2. Giới thiệu công cụ kiểm thử tự động hàm C .......................................................... 32
4.2.1. Tổng quan về công cụ CFT4CUnit .................................................................. 32
4.2.1. Đầu vào công cụ .............................................................................................. 33
4.2.2. Đầu ra công cụ .................................................................................................. 34
4.2.2.1. Đồ thị dòng điều khiển ............................................................................ 34
4.2.2.2. Tập đường kiểm thử ................................................................................ 35
4.2.2.3. Tập ca kiểm thử ....................................................................................... 36
4.2.2.4. Biểu thức chuẩn SMT-Lib ....................................................................... 37
4.2.2.5. Kiểm thử vòng lặp đơn ............................................................................ 37
4.2.2.6. Kiểm thử vòng lặp lồng nhau .................................................................. 38
4.2.3. Thực nghiệm ..................................................................................................... 39
4.2.4. Ý nghĩa thực nghiệm ....................................................................................... 43
Chương 5.

Kết luận .................................................................................................................. 45


DANH SÁCH BẢNG

Bảng 1. Độ ưu tiên các toán tử ...................................................................................................... 26
Bảng 2. So sánh CFT4CUnit, công cụ đề xuất trong [5] và PathCrawler ..................................... 40

Bảng 3. Kiểm thử vòng lặp đơn sử dụng công cụ CFT4CUnit ..................................................... 40
Bảng 4. Kiểm thử hai vòng lặp lồng nhau hàm SelectionSort sử dụng công cụ CFT4CUnit ....... 42

DANH SÁCH KÝ HIỆU, CHỮ VIẾT TẮT

AST

Abstract Syntax Tree

CFG

Control Flow Graph

CDT

C/C++ Development Tooling

CVC

Cooperating Validity Checker

DIMACS

Center for Discrete Mathematics and Theoretical Computer Science

SMT-Solver

Satisfiability Modulo Theories Solver

SAT


Boolean Satisfiability Problem

T-Solver

Theory-specific Solvers

SE

Symbolic Execution


DANH SÁCH HÌNH VẼ

Hình 2.1. Quy trình chung của kiểm thử hộp trắng dòng điều khiển theo hướng động. ................. 5
Hình 2.2: Ví dụ một luật chèn mã nguồn trong DMS/SRT. ............................................................ 6
Hình 2.3. Mã nguồn hàm triangle sau khi thêm khối mã nguồn mới. ............................................. 6
Hình 2.4. Quy trình chung của kiểm thử hộp trắng dòng điều khiển theo hướng tĩnh. ................... 7
Hình 2.5: Các cấu trúc điều khiển phổ biến. ................................................................................... 9
Hình 3.1. Quy trình kiểm thử một hàm C theo phương pháp đề xuất. .......................................... 12
Hình 3.2. Thuật toán sinh CFG từ mã nguồn ................................................................................ 13
Hình 3.3. Mã nguồn hàm average. ................................................................................................ 14
Hình 3.4. CFG hàm average tiêu chuẩn phủ câu lệnh, phủ nhánh. ............................................... 15
Hình 3.5. CFG điều kiện kép (a>=0 || ((b>=0 && c>=0) || b+c>=0) || a+b+c>=0). ...................... 16
Hình 3.6. Thuật toán sinh tập đường đi độc lập từ CFG. .............................................................. 17
Hình 3.7. Thuật toán sinh đường kiểm thử vòng lặp. .................................................................... 18
Hình 3.8. Thuật toán sinh đường kiểm thử vòng lặp trong. .......................................................... 19
Hình 3.9. Thuật toán sinh đường kiểm thử vòng lặp ngoài. .......................................................... 20
Hình 3.10. Ví dụ một hệ ràng buộc. .............................................................................................. 21
Hình 3.11. Thuật toán sinh hệ ràng buộc từ đường kiểm thử. ....................................................... 21

Hình 3.12. Quá trình rút gọn câu lệnh. .......................................................................................... 22
Hình 3.13. Mô tả đầu vào, đầu ra SMT-Solver. ............................................................................ 24
Hình 3.14. Ví dụ hệ ràng buộc tuân theo chuẩn SMT-Lib. ........................................................... 25
Hình 3.15. Quá trình chuyển một biểu thức trung tố về chuẩn SMT-Lib. .................................... 25
Hình 3.16. Thuật toán xây dựng biểu thức hậu tố. ........................................................................ 27
Hình 3.17. Thuật toán xây dựng cây biểu thức từ biểu thức hậu tố. ............................................. 28
Hình 3.18. Thuật toán duyệt cây biểu thức.................................................................................... 29
Hình 4.1. Minh họa cây AST ứng với mã nguồn return x*3 ........................................................ 32


Hình 4.2. Giao diện công cụ đề xuất. ............................................................................................ 33
Hình 4.3. Ví dụ đầu vào công cụ CFT4CUnit. .............................................................................. 33
Hình 4.4. Đồ thị CFG tiêu chí phủ câu lệnh và phủ nhánh. .......................................................... 34
Hình 4.5. Đồ thị CFG tiêu chí phủ điều kiện con. ......................................................................... 34
Hình 4.6. Đường đi tương ứng trên CFG được bôi đỏ khi click vào một đường kiểm thử bất kì. 35
Hình 4.7. Tập đường kiểm thử thỏa mãn phủ câu lệnh hàm foo. .................................................. 35
Hình 4.8. Tập đường kiểm thử thỏa mãn phủ nhánh hàm foo....................................................... 35
Hình 4.9. Tập đường kiểm thử thỏa mãn phủ điều kiện con hàm foo. .......................................... 36
Hình 4.10. Tập đường đi độc lập để sinh tập đường kiểm thử phủ nhánh và phủ câu lệnh. ......... 36
Hình 4.11. Ca kiểm thử thỏa mãn đường đi màu đỏ sinh theo kĩ thuật ngẫu nhiên và dùng SMTSolver. ............................................................................................................................................ 36
Hình 4.12. Hệ ràng buộc chuẩn SMT-Lib tương ứng với đường kiểm thử màu đỏ. ..................... 37
Hình 4.13. Kiểm thử vòng lặp đơn hàm tinh_tong. ....................................................................... 38
Hình 4.14. Kiểm thử một đường kiểm thử chứa hai vòng lặp lồng nhau trong hàm SelectionSort.
....................................................................................................................................................... 38


Chương 1. Đặt vấn đề
Ngày nay, ngôn ngữ C là một trong những ngôn ngữ lập trình phổ biến để phát triển
các hệ thống nhúng nói riêng, các phần mềm hệ thống nói chung và các phần mềm ứng
dụng. Các thống kê trên githut1 và TIOBE2 cho thấy ngôn ngữ C là một trong mười ngôn

ngữ lập trình phổ biến nhất năm 2014.
Thực tế, các phần mềm (đặc biệt là phần mềm hệ thống) thường yêu cầu cao về chất
lượng nên đòi hỏi quá trình kiểm thử thực hiện khắt khe và nghiêm ngặt. Vì thế, kiểm thử
hộp trắng được coi là một kĩ thuật an toàn và hiệu quả nhằm đảm bảo độ tin cậy cao của
phần mềm. Ưu điểm của kiểm thử hộp trắng là tìm lỗi bằng cách xem xét trực tiếp trên
mã nguồn trong khi kiểm thử hộp đen chỉ phát hiện được những lỗi dựa trên tài liệu đặc tả
phần mềm. Rõ ràng, dù tài liệu đặc tả tốt đến đâu, nếu kiểm thử viên chỉ tìm kiếm lỗi dựa
trên đặc tả sẽ không thể phát hiện được những lỗi lập trình tiềm ẩn gây nên lỗi khi chạy
phần mềm, vì thế chỉ sử dụng kiểm thử hộp đen là chưa đủ để thỏa mãn tiêu chí độ tin cậy
cao.
Trong bối cảnh ngành công nghiệp phần mềm hiện nay, kiểm thử hộp trắng cần
được tự động hóa hết mức có thể [1]. Nói chung, kiểm thử là một quá trình rất tốn thời
gian, công sức và chi phí có thể chiếm 40% – 60% tổng chi phí trong toàn bộ quá trình
phát triển phần mềm [2]. Thêm nữa, độ phức tạp mã nguồn của các phần mềm ngày càng
tăng khiến khối lượng mã nguồn cần kiểm thử hộp trắng không chỉ tăng lên mà còn khó
phân tích hơn rất nhiều. Vì thế, kiểm thử tự động là một giải pháp hiệu quả nhằm giúp
kiểm thử viên bớt nhàm chán, giảm thiểu thời gian, công sức và chi phí trong khi vẫn đảm
bảo độ tin cậy cao của phần mềm. Ngoài ra, kiểm thử tự động không chỉ có ý nghĩa khi dự
án không đủ tài nguyên mà còn trong kiểm thử hồi quy khi phần mềm cần sửa đổi hoặc
nâng cấp.
Trong phương pháp kiểm thử hộp trắng, kiểm thử viên không chỉ cần hiểu rõ giải
thuật mà còn cần có các kỹ năng và kiến thức tốt về ngôn ngữ lập trình viết mã nguồn,
nhằm hiểu rõ mã nguồn cần kiểm thử. Hơn nữa, việc áp dụng các kĩ thuật kiểm thử hộp

1

github là nơi lưu trữ mã nguồn trực tuyến rất phổ biến và mạnh mẽ

2


Tiêu chí đánh giá tính phổ biến ngôn ngữ lập trình dựa trên số kết quả tìm kiếm trả về khi truy vấn tên ngôn ngữ lập
trình trên các trên mạng nổi tiếng gồm Google, Google Blogs, MSN, Yahoo, Baidu, Wikipedia và Youtube

1


trắng thường tốn thời gian và công sức nhất là khi mã nguồn cần kiểm thử có độ phức tạp
cao. Vì vậy, các kĩ thuật kiểm thử hộp trắng chủ yếu được sử dụng cho kiểm thử đơn vị.
Kiểm thử hộp trắng có hai kĩ thuật phổ biến là kiểm thử hộp trắng dòng điều khiển
và kiểm thử hộp trắng dòng dữ liệu. Kiểm thử hộp trắng dòng dữ liệu là kĩ thuật tìm kiếm
lỗi thường hay xuất hiện liên quan đến phép gán và sử dụng các biến trong chương trình.
Trong khi đó, kiểm thử hộp trắng dòng điều khiển tập trung kiểm thử tính đúng đắn của
các giải thuật sử dụng trong chương trình. Mỗi một kĩ thuật kiểm thử nêu trên đều có thế
mạnh riêng và không thể thay thế cho nhau được.
Hai kĩ thuật phổ biến trong kiểm thử hộp trắng dòng điều khiển là theo hướng tĩnh
và hướng động. Dù là hướng tĩnh hay hướng động, mục đích cuối cùng là làm sao sinh tập
ca kiểm thử đủ tốt để kiểm tra tính đúng đắn mã nguồn. Các công cụ kiểm thử hướng
động khá phổ biến gồm PathCrawler[11], CAUT3, CREST4. Theo cách tiếp cận này, mã
nguồn sẽ được bổ sung thêm các câu lệnh mới để lưu vết đường đi khi thực thi một bộ
đầu vào. Mỗi một đường đi tương ứng với một hệ ràng buộc, ca kiểm thử tiếp theo được
sinh ra bằng cách phủ định hệ ràng buộc đó. Hạn chế thứ nhất, nếu không tìm được ca
kiểm thử đầu tiên, hay hệ ràng buộc đầu tiên, quá trình kiểm thử không thể tiếp tục. Hạn
chế thứ hai, số bộ kiểm thử sinh ra tương đối lớn (hoặc không xác định) do số lượng hệ
ràng buộc phủ định không ít, đặc biệt với vòng lặp có biến lặp lớn hoặc số lần lặp không
xác định. Hạn chế thứ ba, thời gian sinh ca kiểm thử lâu hơn do phải thực thi lại mã
nguồn nhiều lần trong môi trường chạy. Hạn chế thứ tư, số lượng hệ ràng buộc cần giải
khá lớn (đặc biệt mã nguồn có vòng lặp) và tính đa dạng hệ ràng buộc nên chỉ dùng kĩ
thuật sinh ngẫu nhiên là không khả thi mà phải sử dụng thêm SMT-Solver. Tuy các công
cụ này tận dụng thế mạnh SMT-Solver, tổng chi phí thời gian sinh ca kiểm thử vẫn hơn
đáng kể so với kiểm thử tĩnh.

Khóa luận này đề xuất cách sinh ca kiểm thử cho một hàm C sử dụng kĩ thuật kiểm
thử hộp trắng dòng điều khiển theo hướng tĩnh để giải quyết những hạn chế nêu trên. Tư
tưởng chính của phương pháp đề xuất là tập trung phân tích cấu trúc mã nguồn để sinh ca
kiểm thử thay vì thực thi mã nguồn lặp lại nhiều lần. Kết quả là thời gian sinh tập ca kiểm
thử nhanh hơn do giảm bớt số lần thực thi mã nguồn. Hơn nữa, số lượng ca kiểm thử tối
3

/>
4

/>
2


thiểu thay vì khá lớn mà vẫn đảm bảo tính đúng đắn cao của mã nguồn. Ngoài ra, thời
gian sinh một ca kiểm thử nhanh hơn do tận dụng thế mạnh công cụ SMT-Solver. Cuối
cùng, bởi vì có sự kết hợp kĩ thuật sinh ngẫu nhiên và tận dụng thế mạnh công cụ SMTSolver nên giải được nhiều dạng hệ ràng buộc khác nhau.
Phần còn lại khóa luận được trình bày như sau. Đầu tiên, chương 2 giới thiệu tổng
quan và đưa ra sự so sánh về kĩ thuật kiểm thử hộp trắng dòng điều khiển theo hướng tĩnh
và hướng động. Tiếp theo, phương pháp đề xuất dựa trên kĩ thuật kiểm thử hộp trắng
dòng điều khiển theo hướng tĩnh được trình bày trong chương 3. Sau đó, chương 4 mô tả
công cụ triển khai phương pháp đề xuất và thực nghiệm. Cuối cùng, chương 5 trình bày
tóm tắt các kết quả đã đạt được, kết luận, những hạn chế và hướng nghiên cứu phát triển
trong tương lai.

3


Chương 2. Tổng quan kĩ thuật kiểm thử hộp trắng dòng điều khiển
Ở phần này, khóa luận trình bày các kiến thức tổng quan về kiểm thử hộp trắng dòng

điều khiển gồm hai kĩ thuật kiểm thử hướng tĩnh và hướng động, đồng thời đưa ra sự so
sánh về ưu điểm và nhược điểm của từng kĩ thuật.
2.1. Tổng quan kĩ thuật kiểm thử hộp trắng dòng điều khiển
Kiểm thử hộp trắng dòng điều khiển chia ra gồm kiểm thử hướng tĩnh và kiểm thử
hướng động. Đầu vào của hai kĩ thuật này đều là mã nguồn và tiêu chí phủ kiểm thử. Sau
một loạt quá trình phân tích, đầu ra tương ứng là tập ca kiểm thử. Mỗi một kĩ thuật đều có
những ưu điểm và hạn chế riêng. Mục tiêu của kiểm thử hộp trắng dòng điều khiển là tìm
tập ca kiểm thử tối thiểu nhưng đạt được độ phủ tối đa.
2.2. Quy trình chung của kiểm thử hộp trắng dòng điều khiển theo hướng động
Theo kĩ thuật này, mã nguồn sẽ được thêm các đoạn chương trình con trước khi thực
thi trong môi trường chạy. Hình 2.1 trình bày quy trình chung của kiểm thử động. Nhìn
chung, kĩ thuật này gồm 6 bước cơ bản được diễn giải theo thứ tự dưới đây:
Bước 1.

Chèn thêm các đoạn mã nguồn mới vào mã nguồn cần kiểm thử.

Bước 2.

Chọn ngẫu nhiên một tập giá trị đầu vào hợp lệ làm ca kiểm thử đầu tiên.

Bước 3. Thực thi chương trình với bộ giá trị vừa tìm được. Nếu không thực thi
được, quay lại bước 2 để sinh bộ giá trị khác.
Bước 4. Tìm tập các câu lệnh đã được đi qua với bộ giá trị ở bước 3 để xây dựng
được hệ ràng buộc tương ứng.
Bước 5. Phủ định hệ ràng buộc thu được ở bước 4 để sinh các hệ ràng buộc mới
có tác dụng sinh các ca kiểm thử kế tiếp. Nếu không thể sinh hệ phủ định nào
khác, thuật toán kết thúc.
Bước 6. Giải hệ ràng buộc thu được ở bước 5 để sinh ca kiểm thử kế tiếp. Nếu
không có ca kiểm thử nào thỏa mãn, quay về bước 5 để tìm hệ ràng buộc phủ
định mới sao cho khác hệ ràng buộc hiện tại. Ngược lại, quay lại bước 3 để

sinh ca kiểm thử kế tiếp.

4


Source
code
Tiêu chí
phủ

Pha chèn thêm khối
lệnh mới
Tìm ca kiểm thử
khởi đầu ngẫu nhiên
Thực thi ca kiểm
thử vừa tìm được
Tái tạo đường thực thi
Tạo đường thực thi mới

Kết
thúc

False

Tìm được ca
kiểm thử mới

True

Hình 2.1. Quy trình chung của kiểm thử hộp trắng dòng điều khiển theo hướng động.


Trong bước 1, quá trình chèn thêm khối mã nguồn mới vào mã nguồn cần kiểm thử
được tiến hành một cách tự động. Công cụ DMS/SRT5 được đánh giá khá mạnh mẽ để
thực hiện pha này. Đoạn mã nguồn thêm vào có chức năng đánh dấu, thoát chương trình
hoặc ghi thông tin về quá trình thực thi ra tệp, v.v. Để làm được điều này, chúng tôi cần
xây dựng các luật chèn thêm mã nguồn mới vào mã nguồn cần kiểm thử.
Với công cụ DMS/SRT, mỗi một luật bắt đầu với từ khóa rule và theo sau là tên đặt
cho luật. Từ khóa rewrite to nêu cách biến đổi đoạn mã nguồn gốc về đoạn mã nguồn
mới. Kiểu dữ liệu có thể là expression (ứng với biểu thức), statement (ứng với câu lệnh
gán hoặc khởi tạo), type (ứng với kiểu dữ liệu), identifier (ứng với định danh như tên
biến, tên hàm), v.v. Hình 2.2 mô tả một luật chèn thêm câu lệnh đánh dấu vào khối lệnh
điều khiển rẽ nhánh. Cụ thể, biến mảng visited đánh dấu vị trí câu lệnh đi qua được bổ

5

/>
5


sung vào mã nguồn ban đầu ngay sau mỗi khối lệnh điều khiển rẽ nhánh. Hình 2.3 đưa ra
mã nguồn triangle sau khi áp dụng luật.

Hình 2.2: Ví dụ một luật chèn mã nguồn trong DMS/SRT.

Hình 2.3. Mã nguồn hàm triangle sau khi thêm khối mã nguồn mới.

2.3. Quy trình chung của kiểm thử hộp trắng dòng điều khiển theo hướng tĩnh
Trong kiểm thử tĩnh, mã nguồn không được thực thi trong môi trường chạy để sinh
ca kiểm thử. Trong kiểm thử tĩnh, quá trình chạy ca kiểm thử chỉ thực hiện duy nhất một


6


lần với từng ca kiểm thử để tính toán giá trị trả về và đảm bảo ca kiểm thử thực thi không
có vấn đề. Các bước tổng quát trong kĩ thuật này được trình bày ở Hình 2.4. Đầu tiên, đồ
thị dòng điều khiển được xây dựng dựa trên mã nguồn và tiêu chí phủ kiểm thử. Bước
tiếp theo, từ đồ thị dòng điều khiển chúng tôi xây dựng được tập đường kiểm thử. Mỗi
một đường kiểm thử trong tập đường kiểm thử mô tả hành vi chương trình với một miền
bộ đầu vào nào đó. Sau đó, pha tìm ca kiểm thử thỏa mãn đường kiểm thử được tiến hành.
Cuối cùng, ca kiểm thử được thực thi trong môi trường chạy.
Source code

Xây dựng đồ thị
dòng điều khiển

Tiêu chí phủ
Xây dựng tập
đường kiểm thử
Tìm tập ca kiểm thử
Thực thi tập ca
kiểm thử
Kết thúc
Hình 2.4. Quy trình chung của kiểm thử hộp trắng dòng điều khiển theo hướng tĩnh.

2.3.1. Các tiêu chí phủ kiểm thử
Tiêu chí phủ kiểm thử là một thước đo để đánh giá tính đúng đắn của mã nguồn cần
kiểm thử với một tập ca kiểm thử nào đó. Tập ca kiểm thử khiến mã nguồn có độ phủ cao
được đánh giá là tốt hơn so với tập ca kiểm thử khác khiến mã nguồn có độ phủ thấp hơn.
Chất lượng mã nguồn được đánh giá tỉ lệ thuận với độ phủ.
Độ phủ được đánh giá dựa trên hai thông số gồm tiêu chí phủ kiểm thử và tập ca

kiểm thử. Công thức tính độ phủ là tỉ lệ các thành phần được kiểm thử trên tổng số các
thành phần cần kiểm thử sau khi đã thực hiện tập ca kiểm thử. Thành phần có thể là câu
lệnh, điểm quyết định, điều kiện con, đường thi hành hoặc là sự kết hợp của chúng.
7


Tiêu chí phủ kiểm thử được giới thiệu lần đầu tiên vào 1963 trong tạp chí hàng
tháng “Communications of the ACM”. Cho tới nay, nhiều tiêu chí phủ kiểm thử được đưa
ra. Khóa luận sử dụng ba tiêu chí phủ kiểm thử phổ biến để đánh giá chất lượng mã nguồn
gồm:
 Phủ câu lệnh: Mỗi một câu lệnh được thực thi ít nhất một lần sau khi chạy tập ca
kiểm thử.
 Phủ nhánh: Mỗi một nhánh đều được đi qua ít nhất một lần sau khi chạy tập ca
kiểm thử.
 Phủ điều kiện con: Mọi nhánh đúng-sai đều được đi qua với một tập ca kiểm thử
nào đó, trong đó các câu lệnh điều kiện kép được phân tách thành các câu lệnh điều
kiện đơn.
2.3.2. Đồ thị dòng điều khiển
Sinh ca kiểm thử dựa trên mã nguồn phức tạp và khó khăn hơn so với sinh ca kiểm
thử dựa trên đồ thị dòng điều khiển (Control Flow Graph – CFG). CFG là một đồ thị có
hướng mô tả cấu trúc lôgic của chương trình một cách trực quan và đơn giản hơn, gồm có
các đỉnh tương ứng với các câu lệnh/nhóm câu lệnh và các cạnh là các dòng điều khiển
giữa các câu lệnh/nhóm câu lệnh. Đỉnh đầu tiên của CFG là trạng thái đầu tiên của hàm,
đỉnh cuối cùng của CFG là trạng thái kết thúc của hàm. Đỉnh i nối đến đỉnh j thì câu lệnh
tương ứng đỉnh j có thể được thực thi sau khi thực hiện câu lệnh tương ứng ở đỉnh i.
Trong ngôn ngữ C, các cấu trúc điều khiển trong CFG gồm tuần tự, rẽ nhánh,
while...do, do...while, for. Hình 2.5 minh họa các cấu trúc điều khiển nêu trên. Trong đó
đỉnh có nhãn c tượng trưng cho câu lệnh điều kiện. Các đỉnh còn lại tượng trưng câu lệnh
gán, khai báo, v.v. Các thành phần cơ bản của đồ thị dòng điều khiển gồm đỉnh xuất phát,
đỉnh xử lí, đỉnh quyết định, đỉnh kết nối và đỉnh kết thúc.

 Đỉnh xuất phát và đỉnh kết thúc: Hai đỉnh này là duy nhất, trong đó đỉnh xuất phát
đại diện cho tên hàm.
 Đỉnh quyết định: Là đỉnh tương ứng với câu lệnh điều kiện trong khối lệnh điều
khiển rẽ nhánh, do...while, while..do. Ví dụ cụ thể, với khối lệnh điều khiển “if (a
> b) { ... }” thì đỉnh quyết định tương ứng với “a > b”.
 Đỉnh kết nối: Là đỉnh có nhiều hơn hai đỉnh khác trỏ đến mà không phải đỉnh quyết
định.
8


 Đỉnh xử lí: Là đỉnh tương ứng với câu lệnh gán, câu lệnh khởi tạo hoặc câu lệnh
khai báo và không phải đỉnh kết nối. Các khối lệnh điều khiển cũng chứa các loại
câu lệnh này. Ví dụ, khối lệnh “for (i = 0; i < 10; i++)” chứa hai đỉnh xử lí gồm
câu lệnh gán “i = 0” và câu lệnh tăng giá trị biến i là “i++”.

Hình 2.5: Các cấu trúc điều khiển phổ biến.

2.3.3. Đường kiểm thử
Với một bộ giá trị đầu vào, một tập các câu lệnh gán, câu lệnh khai báo và câu lệnh
điều kiện được đi qua. Danh sách các câu lệnh này được sắp theo thứ tự thực hiện chính là
một đường đi. Trong số tất cả các đường đi có thể, một tập đường đi được chọn sao cho
thỏa mãn tiêu chí phủ kiểm thử được gọi là tập đường kiểm thử.
Đường kiểm thử là một đường đi từ đỉnh đầu tiên đến đỉnh cuối cùng của CFG được
biểu diễn dưới một tập các đỉnh từ đỉnh v1 đến đỉnh vn, trong đó hai đỉnh liền kề có cạnh
nối với nhau. Nếu cạnh (vi ,vj) (i j) là nhánh false, câu lệnh lưu ở đỉnh vi được viết phủ
định. Tập đường đi độc lập gồm k đường đi PATH1, PATH2, …, PATHk thỏa mãn: giữa
mọi cặp đường đi độc lập PATHi và PATHj (i

j) không chung ít nhất một cạnh trở lên.


Tìm kiếm tập đường kiểm thử là bước trung gian trong quá trình sinh tập ca kiểm
thử. Hai vấn đề liên quan đến tập đường kiểm thử rất quan trọng gồm:
 Vấn đề thực thi được hay không thực thi được. Một đường kiểm thử gọi là thực thi
được nếu tìm kiếm được một ca kiểm thử sao cho khi thực thi trong môi trường
thật thì đường kiểm thử nêu trên được đi qua. Ngược lại, đường kiểm thử gọi là
không thực thi được.
9


 Tính phức tạp mã nguồn. Một mã nguồn gọi là phức tạp nếu chứa nhiều vòng lặp
như nhiều vòng lặp lồng nhau hoặc nhiều vòng lặp nối tiếp nhau, kích thước lớn
hoặc thuật toán phức tạp. Mã nguồn càng phức tạp càng khiến quá trình tìm kiếm
đường kiểm thử trở nên khó khăn hơn và mất thời gian hơn.
2.4. So sánh kĩ thuật kiểm thử hộp trắng dòng điều khiển theo hướng tĩnh và động
Mỗi một kĩ thuật kiểm thử đều có những ưu điểm và hạn chế riêng. Để có cái nhìn
tổng quan về hai kĩ thuật, chúng tôi đưa ra sự so sánh về số ca kiểm thử, thời gian sinh ca
kiểm thử, khả năng kiểm thử vòng lặp, ảnh hưởng bởi phức tạp mã nguồn đối với hai kĩ
thuật.
 Về số ca kiểm thử. Nhìn chung, với mã nguồn chỉ chứa các câu lệnh rẽ nhánh và
không chứa vòng lặp, hai kĩ thuật kiểm thử nêu trên cho số bộ ca kiểm thử như
nhau. Tuy nhiên, trong trường hợp có vòng lặp thì kĩ thuật kiểm thử tĩnh đưa ra số
ca kiểm thử ít hơn so với kiểm thử động. Theo hướng tĩnh, các đường đi chứa vòng
lặp lặp lại một lần sẽ được cấu trúc lại để lặp nhiều hơn một lần. Nói cụ thể hơn, từ
một đường kiểm thử chứa vòng lặp ban đầu sẽ sinh ra một tập các đường kiểm thử
mới dùng để kiểm thử tính đúng đắn vòng lặp. Nếu vòng lặp trong đường kiểm thử
xác định được số lần lặp tối đa thì số đường đi mới sinh ra là bảy. Ngược lại, nếu
vòng lặp không xác định số lần lặp tối đa thì số đường đi mới sinh ra là bốn.
Với mã nguồn chứa vòng lặp, kiểm thử động sử dụng kĩ thuật phủ định hệ để
sinh ca kiểm thử kế tiếp nên số ca kiểm thử có thể rất lớn hoặc không xác định. Cụ
thể, trường hợp số ca kiểm thử rất lớn xảy ra khi vòng lặp có cận lặp lớn, ví dụ,

khối lệnh điều khiển “for (int i = 0; i < 1000; i++)” có số lần lặp tối đa là 1000 lần.
Trường hợp số ca kiểm thử không xác định xảy ra khi số lần lặp không được biết
trước như “while (m!=n){...}”, trong đó m và n là hai tham số kiểu nguyên truyền
vào hàm. Để giải quyết hai vấn đề này, một vài công cụ kiểm thử như PathCrawler
chèn thêm mã nguồn xác định số lần lặp tối đa của mỗi vòng lặp hoặc thêm yêu
cầu thời gian chạy. Tuy nhiên, nhìn chung số ca kiểm thử vẫn khá lớn gây khó
khăn cho quản lí.
 Về thời gian sinh ca kiểm thử. Một cách tổng quan, kiểm thử động thực thi ca kiểm
thử lặp lại nhiều lần nên thời gian sinh ca kiểm thử lâu hơn. Một điểm chung là hai
kĩ thuật đều có bước giải hệ ràng buộc để sinh ca kiểm thử mới. Thời gian giải hệ

10


chiếm tỉ lệ đáng kể trong tổng thời gian sinh ca kiểm thử. Tuy nhiên, các công cụ
có khả năng giải hệ được phát triển khá mạnh mẽ và công bố rộng rãi trong thời
gian gần đây nên sự so sánh về thời gian giải hệ có thể bỏ qua.
 Về khả năng kiểm thử vòng lặp. Kiểm thử tĩnh hướng đến chỉ kiểm thử một vòng
lặp duy nhất tại một thời điểm. Do đó, trong trường hợp có nhiều vòng lặp, chẳng
hạn như đường kiểm thử đi qua hai vòng lặp lồng nhau thì quy trình kiểm thử tiến
hành với từng vòng lặp riêng và tìm cách phá vỡ cấu trúc lặp các vòng lặp còn lại.
Ngược lại, kiểm thử động hướng đến kiểm thử tính đúng đắn của các vòng lặp một
cách đồng thời thay vì riêng rẽ. Tư tưởng này mô phỏng quá trình thực thi trong
thực tế.
 Tính phức tạp mã nguồn. Hiện nay, quy tắc viết mã nguồn rất đa dạng và các quy
tắc mới có thể được đưa ra trong các phiên bản trình biên dịch mới. Kiểm thử tĩnh
bị hạn chế bởi tính phức tạp mã nguồn. Ví dụ, trường hợp mã nguồn chứa các hàm
biến đổi xâu thì kĩ thuật kiểm thử này yêu cầu cần phải xây dựng lại các hàm đó
một cách thủ công. Ngược lại, kiểm thử động không bị ảnh hưởng lớn bởi những
sự thay đổi này và bởi tính phức tạp mã nguồn. Nguyên nhân chính do kiểm thử

động tận dụng thế mạnh trình biên dịch để sinh ca kiểm thử mới.
2.5. Tầm quan trọng của tự động hóa quy trình kiểm thử hộp trắng dòng điều khiển
Ba trong số những nguyên nhân chính dẫn đến vấn đề tự động hóa quy trình kiểm
thử hộp trắng dòng điều khiển gồm:
 Thời gian sinh ca kiểm thử bằng tay khá lâu và dễ dẫn đến sai sót. Nguyên nhân
chính phụ thuộc vào trình độ chuyên môn của kiểm thử viên, độ phức tạp mã
nguồn và chịu áp lực bởi môi trường làm việc.
 Chi phí về nguồn nhân lực cho pha kiểm thử khá tốn kém. Muốn đảm bảo chất
lượng phần mềm (đặc biệt với dự án lớn) thì chi phí nguồn nhân lực càng cao. Do
đó, vấn đề quản lí khối lượng nguồn nhân lực trở nên phức tạp và rắc rối.
 Các thống kê cho thấy chi phí pha kiểm thử có thể chiếm tới 40%-60% tổng chi
phí phát triển dự án phần mềm [2]. Các phần mềm hệ thống, phần mềm doanh
nghiệp, v.v. đều đòi hỏi chất lượng cao nên pha kiểm thử luôn được chú trọng và
không thể bỏ qua. Hơn nữa, mỗi khi phần mềm được nâng cấp thì quá trình kiểm
thử được tiến hành lại dẫn đến chi phí đã cao nay càng cao hơn.
11


Chương 3. Phương pháp kiểm thử tự động hàm C sử dụng kĩ thuật
kiểm thử hộp trắng dòng điều khiển theo hướng tĩnh
Chương này đề xuất phương pháp kiểm thử tự động hàm C sử dụng kĩ thuật kiểm
thử kiểm thử hộp trắng dòng điều khiển theo hướng tĩnh. Phương pháp đề xuất cách xây
dựng đồ thị dòng điều khiển CFG, sinh tập đường đi độc lập, kĩ thuật kiểm thử tính đúng
đắn với hàm đầu vào chứa vòng lặp đơn hoặc hai vòng lặp lồng nhau. Ngoài ra, kĩ thuật
SE được mô tả một cách chi tiết nêu cách xây dựng hệ ràng buộc từ một đường thi hành
bất kì. Tổng quan về SMT-Solver và kĩ thuật sinh ngẫu nhiên được trình bày để giải hệ
ràng buộc sinh ca kiểm thử.
3.1. Tổng quan phương pháp kiểm thử hộp trắng dòng điều khiển theo hướng tĩnh
Hàm C
Độ phủ


Sinh CFG
Sinh tập đường đi độc lập
Sinh tập đường kiểm thử
Sinh đường kiểm thử vòng lặp
Sinh hệ ràng buộc

SMT-Solver

Sinh ca kiểm thử
Sinh ngẫu nhiên

Thực thi ca kiểm thử
Xuất báo cáo
Hình 3.1. Quy trình kiểm thử một hàm C theo phương pháp đề xuất.

Khóa luận đề xuất một phương pháp kiểm thử hàm C sử dụng phương pháp kiểm
thử hộp trắng dòng điều khiển theo hướng tĩnh và cài đặt công cụ hỗ trợ. Đầu vào của bài
12


toán là một tiêu chí phủ kiểm thử và một đơn vị chương trình C chứa các biến số nguyên,
số thực và biến mảng. Đầu ra là tập ca kiểm thử thỏa mãn tiêu chí phủ kiểm thử nêu trên.
Đề xuất được mô tả khái quát ở Hình 3.1. Đầu tiên, mã nguồn được phân tích để sinh
CFG tương ứng với tiêu chí phủ kiểm thử cho trước. Sau đó, chúng tôi xây dựng tập
đường đi độc lập từ CFG nêu trên. Tiếp theo, quá trình phân tích tập đường đi độc lập để
sinh tập đường kiểm thử thỏa mãn tiêu chí phủ kiểm thử được tiến hành. Ngoài ra, để
kiểm thử tính đúng đắn của vòng lặp, các đường kiểm thử mới được xây dựng bằng cách
phân tích các đường kiểm thử chứa vòng lặp. Tiếp theo, các đường kiểm thử được phân
tích sử dụng kĩ thuật SE để sinh ra hệ ràng buộc. Mỗi hệ ràng buộc được giải bằng cách

sử dụng kĩ thuật sinh ngẫu nhiên hoặc sử dụng công cụ SMT-Solver. Nếu sử dụng công
cụ SMT-Solver, các hệ ràng buộc sẽ được chuyển đổi về dạng chuẩn SMT-Lib. Sau khi
có được ca kiểm thử, quá trình thực thi ca kiểm thử được tiến hành để lấy giá trị trả về của
mã nguồn (nếu có) và đảm bảo ca kiểm thử thực thi không lỗi.
3.2. Sinh đồ thị dòng điều khiển từ mã nguồn

Hình 3.2. Thuật toán sinh CFG từ mã nguồn.

13


×