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

Nghiên cứu phương pháp sinh dữ liệu kiểm thử từ mã nguồn và ứng dụng xây dựng hệ thống chấm bài tập lập trình

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 (1.09 MB, 60 trang )

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

NGUYỄN THỊ KHÁNH CHI

PHƢƠNG PHÁP SINH DỮ LIỆU KIỂM THỬ TỰ ĐỘNG
TỪ MÃ NGUỒN VÀ ỨNG DỤNG XÂY DỰNG HỆ THỐNG
CHẤM BÀI LẬP TRÌNH

LUẬN VĂN THẠC SĨ
Ngành: Kỹ Thuật Phần Mềm

HÀ NỘI – 2019


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

NGUYỄN THỊ KHÁNH CHI

PHƢƠNG PHÁP SINH DỮ LIỆU KIỂM THỬ TỰ ĐỘNG
TỪ MÃ NGUỒN VÀ ỨNG DỤNG XÂY DỰNG HỆ THỐNG
CHẤM BÀI LẬP TRÌNH

Ngành: Kỹ Thuật Phần Mềm
Chuyên ngành: Kỹ Thuật Phần Mềm
Mã số: 848 01 03.01

LUẬN VĂN THẠC SĨ
Ngành: Kỹ Thuật Phần Mềm


NGƢỜI HƢỚNG DẪN KHOA HỌC: PGS. TS. Phạm Ngọc Hùng

HÀ NỘI – 2019


VIETNAM NATIONAL UNIVERSITY, HANOI
UNIVERSITY OF ENGINEERING AND TECHNOLOGY

NGUYEN THI KHANH CHI

A METHOD FOR AUTOMATED TEST DATA
GENERATION FROM SOURCE CODE AND
APPLICATION IN BUILDING PROGRAMMING
MARKING SYSTEM

THE MS. THESIS
Major: InformationTechnology

Supervisor: Assoc. Prof. Pham Ngoc Hung

HANOI - 2019


i

MỤC LỤC
MỤC LỤC ........................................................................................................................ i
LỜI CẢM ƠN ................................................................................................................ iii
TÓM TẮT....................................................................................................................... iv
ABSTRACT .................................................................................................................... v

LỜI CAM ĐOAN ........................................................................................................... vi
DANH MỤC THUẬT NGỮ VIẾT TẮT ......................................................................vii
DANH MỤC HÌNH VẼ .............................................................................................. viii
DANH MỤC BẢNG ....................................................................................................... x
Chương 1: Mở đầu ........................................................................................................... 1
Chương 2: Phương pháp sinh dữ liệu kiểm thử dòng điều khiển .................................... 3
2.1 Tổng quan về kiểm thử dòng điều khiển ..................................................................... 3
2.2 Các tiêu chí kiểm thử .................................................................................................. 4
2.3 Xây dựng đồ thị dòng điều khiển ................................................................................ 6
2.3.1.Xây dựng đồ thị dòng điều khiển ứng với tiêu chí phủ câu lệnh và phủ nhánh ..... 8
2.3.2. Xây dựng CFG ứng với tiêu chí phủ điều kiện con ............................................... 9
2.3.3. Phương pháp xây dựng CFG từ mã nguồn Java .................................................. 10
2.4. Sinh đường đi kiểm thử từ đồ thị............................................................................. 12
2.4.1. Sinh đường đi thỏa mãn tiêu chí phủ câu lệnh..................................................... 12
2.4.2. Sinh đường đi thỏa mãn tiêu chí phủ nhánh ........................................................ 13
2.4.3. Sinh đường đi thỏa mãn tiêu chí phủ điều kiện con ............................................ 13
2.4.4. Phương pháp sinh đường đi kiểm thử trên đồ thị ................................................ 14
2.5.

Sinh ca kiểm thử từ đường đi ............................................................................. 15

2.5.1. Sinh dữ liệu kiểm thử .......................................................................................... 15
2.5.2. Sinh đầu ra mong muốn ....................................................................................... 17
2.6 . Sinh các ca kiểm thử giá trị biên và vòng lặp.......................................................... 17
2.6.1.Sinh ca kiểm thử giá trị biên ................................................................................. 18
2.6.2. Sinh ca kiểm thử vòng lặp ................................................................................... 19
Chương 3: Công cụ và thực nghiệm .............................................................................. 22


ii

3.1 Đặc tả hệ thống chấm bài lập trình .......................................................................... 22
3.1.1. Danh sách các tác nhân........................................................................................ 22
3.1.2. Mô tả các ca sử dụng của hệ thống: .................................................................... 24
3.2 . Kiến trúc tổng thể của hệ thống chấm bài lập trình................................................ 27
3.3 Kiến trúc của mô-đun sinh ca kiểm thử tự động ....................................................... 28
3.4 Giới thiệu công cụ sinh ca kiểm thử tự động ............................................................ 29
3.3.1.Giao diện công cụ sinh ca kiểm thử tự động ........................................................ 29
3.3.2.Đồ thị dòng điều khiển ......................................................................................... 29
3.3.3.Tập các đường kiểm thử ....................................................................................... 31
3.3.4. Tập các ca kiểm thử ............................................................................................. 31
3.5 Kết quả thực nghiệm ................................................................................................. 33
Bài toán 1: Bài toán kiểm tra năm nhuận ..................................................................... 33
Bài toán 2: Bài toán tính số ngày trong một tháng ....................................................... 35
Bài toán 3: Tìm ước số chung lớn nhất ......................................................................... 40
3.6 .Ý nghĩa của thực nghiệm.......................................................................................... 44
Chương 4: Kết luận ....................................................................................................... 46
TÀI LIỆU THAM KHẢO ............................................................................................. 47


iii

LỜI CẢM ƠN
Trước tiên, tôi xin gửi lời cảm ơn chân thành và sâu sắc đến người thầy đáng
kính PGS. TS. Phạm Ngọc Hùng - người đã trực tiếp hướng dẫn, chỉ bảo và giúp đỡ
tôi trong suốt quá trình tôi học tập và nghiên cứu tại trường. Nhờ có lòng tốt của thầy,
sự say mê nghiên cứu khoa học, kiến thức uyên thâm và sự hướng dẫn tận tình, tôi đã
vượt qua được những khó khăn từ phía gia đình để tiếp tục học tập, nghiên cứu và
hoàn thiện luận văn này.
Tôi xin chân thành cảm ơn các thầy cô giáo khoa Công nghệ thông tin, trường
Đại học Công nghệ, Đại học Quốc Gia Hà Nội đã nhiệt tình giảng dạy, truyền đạt

những kiến thức quý báu trong suốt quá trình tôi học tập và nghiên cứu tại trường.
Tôi xin chân thành cảm ơn những người thân trong gia đình, các bạn bè, đồng
nghiệp luôn tạo điều kiện, giúp đỡ động viên tôi trong công tác nghiên cứu khoa học.
Cuối cùng, tôi xin cảm ơn ban giám hiệu trường THPT Ngô Gia Tự - Từ Sơn Bắc Ninh nơi tôi công tác, các đồng nghiệp và các em học sinh khối 11 đã tạo điều
kiện tối đa, đóng góp những nhận xét khách quan cho đề tài nghiên cứu để tôi có thể
hoàn thành luận văn Thạc sỹ tại trường Đại học Công nghệ - Đại học Quốc Gia Hà
Nội.


iv

TÓM TẮT
Luận văn tập trung nghiên cứu phương pháp sinh các ca kiểm thử từ mã nguồn
và ứng dụng trong việc tự động chấm các bài tập lập trình của học sinh viết bằng ngôn
ngữ Java nhằm hỗ trợ các giáo viên Tin học tại các Trường Trung học phổ
thông/Trung học cơ sở trong việc sinh các ca kiểm thử và chấm các bài tập lập trình
của học sinh. Với mỗi bài tập, giáo viên sẽ cung cấp mã nguồn mẫu (mã nguồn không
có lỗi). Dựa vào mã nguồn này, chúng ta sẽ tiến hành phân tích nhằm xây dựng đồ thị
dòng điều khiển của mã nguồn. Tiếp đến, các đường đi của đồ thị ứng với các dòng
điều khiển có thể có của chương trình sẽ được sinh. Từ các đường đi này, chúng ta sẽ
xây dựng hệ ràng buộc chứa các điều kiện của các tham số. Việc sinh dữ liệu kiểm thử
trên đường thực thi chính là việc giải hệ ràng buộc trên đường đi tương ứng. Khi có dữ
liệu kiểm thử, chúng ta sẽ sử dụng đầu ra của mã nguồn chuẩn để sinh giá trị đầu ra
mong muốn tương ứng. Cùng với các ca kiểm thử đã được sinh ra, luận văn còn
nghiên cứu các giải pháp để sinh các ca kiểm thử cho các vòng lặp và sinh các ca kiểm
thử tại các biên của từng tham số ứng với miền giá trị và đặc tả của bài toán.
Luận văn cũng đã tiến hành xây dựng công cụ hỗ trợ và áp dụng thử nghiệm với
các chương trình đơn giản nhằm minh chứng cho tính đúng đắn và tính hiệu quả của
phương pháp đề xuất. Tuy nhiên, công cụ cài đặt chưa được hoàn thiện và cần được
tiếp tục phát triển nhằm có một công cụ hỗ trợ giáo viên như đã nêu ở trên.


Từ khóa: Kiểm thử tự động, sinh dữ liệu kiểm thử, độ phủ kiểm thử, kiểm thử hộp
trắng.


v

ABSTRACT
The thesis focuses on studying the method of testing data from source code and
applying in automatically marking students' programming exercises written in Java
language to support Informatics teachers at high schools. information / junior high
school in testing test cases and marking students' programming exercises. For each
teacher exercise, the teacher will provide sample source code (source code without
errors). Based on this source code, we will conduct source code analysis to build
control line graph of source code. Next, we will generate the graph's paths
corresponding to the possible control lines of the program. From these paths, we will
build the binding system without the conditions of the parameters. Generating test data
corresponding to the corresponding path is the finding of a solution of the
corresponding system of equations. Whenever there is test data, we will use the
specification to generate the desired output values. Along with the test cases as born,
the thesis also studies solutions to generate test cases for loops and generate test cases
at the boundaries of each parameter corresponding to the value domain and
specification of the problem.
The thesis has also developed support tools and applied experiments with simple
programs to demonstrate the correctness and effectiveness of the proposed method.
However, the installation tool has not been completed and needs to be further
developed in order to have a teacher support tool as mentioned above.

Keywords: Automated testing, test data generation, test coverage, white-box
testing



vi

LỜI CAM ĐOAN
Tôi xin cam đoan luận văn Thạc sỹ Công nghệ thông tin "Phương pháp sinh dữ
liệu kiểm thử từ mã nguồn và ứng dụng xây dựng hệ thống chấm bài tập lập trình" là
công trình nghiên cứu của tôi dưới sự hướng dẫn của Thầy hướng dẫn, không sao chép
lại của người khác. Trong toàn bộ nội dung luận văn, những điều được trình bày là của
cá nhân tôi hoặc là được tổng hợp từ các nguồn tài liệu khác. Tất cả các nguồn tài liệu
tham khảo đều có trích dẫn cụ thể và hợp pháp.
Tôi xin hoàn toàn chịu trách nhiệm và chịu mọi hình thức kỷ luật theo quy định
của trường Đại học Công Nghệ - Đại học Quốc Gia Hà Nội cho lời cam đoan này.
Hà Nội, ngày 26 tháng 03 năm 2019

Nguyễn Thị Khánh Chi


vii

DANH MỤC THUẬT NGỮ VIẾT TẮT
STT

Từ viết tắt

Từ đầy đủ

Ý nghĩa

1


AST

Abstract Syntax Tree

Cây cú pháp trừu tượng

2

CFG

Control Flow Graph

Đồ thị dòng điều khiển

3

EO

Expected Output

Giá trị đầu ra mong đợi

4

JDT

Java Development Tooling

5


RO

Real Output

Giá trị đầu ra thực tế

6

SE

Symbolic Excecution

Thực thi tượng trưng

7

SMT-Solver

Satisfiability Modulo Theories
Solver

8

TC

Test Case

Ca kiểm thử



viii

DANH MỤC HÌNH VẼ
Hình 2.1. Tổng quan quy trình kiểm thử dòng điều khiển ..............................................3
Hình 2.2. Mã nguồn hàm laNamNhuan...........................................................................5
Hình 2.3. Các thành phần cơ bản của đồ thị dòng điều khiển .........................................7
Hình 2.4. Các cấu trúc điều khiển cơ bản của đồ thị dòng điều khiển ............................ 7
Hình 2.5. Mã nguồn và CFG ứng với tiêu chí phủ câu lệnh hàm laNamNhuan .............8
Hình 2.6. Mã nguồn và CFG ứng với tiêu chí phủ điều kiện con hàm laNamNhuan .....9
Hình 2.7. Mã nguồn và CFG ứng với tiêu chí phủ câu lệnh hàm laNamNhuan ...........13
Hình 2.8. Mã nguồn và CFG ứng với tiêu chí phủ điều kiện con hàm laNamNhuan ...14
Hình 2.9. Mã nguồn và CFG ứng với tiêu chí phủ nhánh hàm giaithua .......................20
Hình 3.1. Biểu đồ ca sử dụng của hệ thống chấm bài lập trình. ....................................23
Hình 3.2. Kiến trúc tổng thể của hệ thống chấm bài lập trình.......................................27
Hình 3.3. Kiến trúc của mô-đun sinh ca kiểm thử tự động ...........................................28
Hình 3.4. Giao diện của công cụ sinh ca kiểm thử tự động ..........................................29
Hình 3.5. CFG ứng với tiêu chí phủ câu lệnh và phủ nhánh hàm laNamNhuan ...........30
Hình 3.6. CFG ứng với tiêu chí phủ điều kiện con hàm laNamNhuan ......................... 30
Hình 3.7. Chi tiết các đường kiểm thử cho tiêu chí phủ nhánh hàm laNamNhuan ......31
Hình 3.8. Chi tiết các ca kiểm thử cho tiêu chí phủ câu lệnh của hàm laNamNhuan ...32
Hình 3.9. Kết quả kiểm thử được xuất dưới dạng MS. Excel hàm laNamNhuan .........32
Hình 3.10. Mã nguồn chuẩn của hàm laNamNhuan .....................................................33
Hình 3.11. Chi tiết ca kiểm thử cho tiêu chí phủ điều kiện con ham laNamNhuan ......33
Hình 3.12. Mã nguồn hàm laNamNhuan1 của học sinh thứ nhất .................................34
Hình 3.13. Mã nguồn hàm laNamNhuan2 của học sinh thứ hai ...................................34
Hình 3.14. Mã nguồn chuẩn của hàm songay ............................................................... 36
Hình 3.15. Chi tiết ca kiểm thử cho tiêu chí phủ điều kiện con hàm songay ................36
Hình 3.16. Mã nguồn hàm songayhs_1 của học sinh thứ nhất ......................................37
Hình 3.17. Mã nguồn hàm songayhs_2 của học sinh thứ hai ........................................37

Hình 3.18. Mã nguồn chuẩn của hàm timuscln ............................................................. 40
Hình 3.19. Chi tiết các ca kiểm thử cho tiêu chí phủ nhánh hàm timuscln ...................40


ix
Hình 3.20. Chi tiết các ca kiểm thử phủ tất cả các nhánh hàm timuscln .......................41
Hình 3.21. Mã nguồn hàm timuscnl_1 của học sinh thứ nhất .......................................41
Hình 3.22. Mã nguồn hàm timuscln_2 của học sinh thứ hai .........................................41


x

DANH MỤC BẢNG
Bảng 2.1. Các ca kiểm thử cho tiêu chí phủ câu lệnh của hàm laNamNhuan.................5
Bảng 2.2. Các trường hợp cần kiểm thử với tiêu chí phủ nhánh cho hàm laNamNhuan 5
Bảng 2.3. Các trường hợp cần kiểm thử với tiêu chí phủ điều kiện con của hàm
laNamNhuan ....................................................................................................................6
Bảng 2.4. Các ca kiểm thử cho tiêu chí phủ điều kiện con hàm laNamNhuan ...............6
Bảng 2.5. Dữ liệu kiểm thử cho tiêu chí phủ điều kiện con hàm laNamNhuan ............16
Bảng 2.6. Các ca kiểm thử cho tiêu chí phủ câu lệnh hàm laNamNhuan .....................17
Bảng 2.7. Các ca kiểm thử giá trị biên cho hàm laNamNhuan .....................................18
Bảng 2.8. Các ca kiểm thử cho tiêu chí phủ nhánh hàm giaithua .................................20
Bảng 2.9. Các ca kiểm thử vòng lặp for hàm giaithua ..................................................21
Bảng 3.1. Danh sách tác nhân của hệ thống chấm bài lập trình. ...................................22
Bảng 3.2. Danh sách các ca sử dụng của hệ thống chấm bài lập trình. ......................... 23
Bảng 3.3. Kết quả kiểm thử bài tập kiểm tra năm nhuận của hai học sinh ...................34
Bảng 3.4. Các ca kiểm thử giá trị biên cho hàm laNamNhuan .....................................35
Bảng 3.5. Kết quả kiểm thử giá trị biên bài tập kiểm tra năm nhuận của hai học sinh .35
Bảng 3.6. Kết quả kiểm thử bài tập tính số ngày trong tháng của hai học sinh ............38
Bảng 3.7. Các ca kiểm thử giá trị biên cho hàm songay ...............................................39

Bảng 3.8. Kết quả kiểm thử giá trị biên bài tập tính số ngày trong tháng của hai học
sinh.................................................................................................................................39
Bảng 3.9. Kết quả kiểm thử bài tập tìm ước số chung lớn nhất của hai học sinh .........42
Bảng 3.10. Các ca kiểm thử giá trị biên cho hàm timuscln ...........................................43
Bảng 3.11. Kết quả kiểm thử giá trị biên bài tập tìm uscln của hai của học sinh ........43
Bảng 3.12. Các ca kiểm thử vòng lặp while cho hàm timuscln ....................................44
Bảng 3.13. Kết quả kiểm thử vòng lặp while cho hàm tìm uscln của hai học sinh .......44


1

Chƣơng 1: Mở đầu
Hiện nay, môn học lập trình đã được đưa vào giảng dạy ở các trường Trung học
phổ thông (THPT) trên toàn quốc, giúp các em học sinh làm quen với công việc lập
trình và làm quen dần với tư duy thiết kế các thuật toán. Ngôn ngữ lập trình được sử
dụng để giảng dạy trong hầu hết các trường THPT là Pascal. Tuy nhiên, theo chương
trình giáo dục THPT mới, trên cơ sở định hướng lập trình và tùy chọn ngôn ngữ, nhiều
trường THPT đã bước đầu đưa các ngôn ngữ lập trình phổ biến như C, Java, v.v. vào
giảng dạy. Trong quá trình giảng dạy, công việc chấm bài tập lập trình đối với người
giáo viên thường diễn ra thủ công và tiềm ẩn nhiều sai sót. Do thời gian chấm bài có
hạn nên việc không phát hiện ra các lỗi trong bài lập trình là không tránh khỏi. Điều
này dẫn đến điểm chấm chưa thực sự chính xác và công bằng. Làm thế nào để công
việc chấp bài lập trình được dễ dàng hơn với các giáo viên, cũng như đảm bảo tính
chính xác, rút ngắn thời gian chấm bài là mục tiêu cần hướng tới.
Đối với các bài tập lập trình, việc chấm bài chính là rà soát để phát hiện các lỗi
có thể có trên mã nguồn của bài tập học sinh. Khi chương trình xuất hiện lỗi cú pháp,
các lỗi sẽ được trình biên dịch phát hiện để người lập trình sửa lỗi. Tuy nhiên, ngay cả
khi một chương trình không có lỗi cú pháp thì chương trình vẫn chưa chắc đã đúng vì
lỗi có thể xảy ra trong quá trình thiết kế giải thuật. Làm thế nào để hỗ trợ giáo viên
kiểm tra xem chương trình có thực hiện đúng với đặc tả yêu cầu của bài toán hay

không, hoặc đúng bao nhiêu phần so với đặc tả của bài toán chính là mục tiêu của quá
trình chấm bài. Hơn nữa, việc giáo viên cung cấp các cơ chế cho phép học sinh tự làm
bài và tương tác qua các ứng dụng nhằm nâng cao khả năng tự học và tăng cường chất
lượng là một xu hướng tất yếu trong hệ thống giáo dục thời gian tới. Vì vậy, nhu cầu
về bài toán này càng cấp thiết hơn.
Để giải quyết vấn đề này, ứng với mỗi bài toán, giáo viên phải sinh ra một bộ ca
kiểm thử đủ tốt (có khả năng phát hiện tất cả các lỗi có thể có của bài lập trình của học
sinh). Bộ ca kiểm thử này sau đó sẽ được sử dụng để chấm các chương trình cho học
sinh nộp (tự động hoặc thủ công tùy thuộc vào phương pháp và công cụ mà giáo viên
sử dụng). Hiện tại, việc sinh ra các bộ ca kiểm thử như vậy là vượt ngoài khả năng của
các giáo viên Trung học phổ thông. Vì vậy, có một công cụ tự động hỗ trợ giáo viên
giải quyết bài toán này là một vấn đề cấp thiết, có ý nghĩa thực tiễn cao. Một trong
những giải pháp để giải quyết vấn đề này là sinh dữ liệu kiểm thử từ mã nguồn sử
dụng phương pháp kiểm thử dòng dữ liệu [2, 3, 4, 8, 9, 11]. Trong phương pháp này,
ứng với đặc tả của mỗi bài toán, thay vì yêu cầu giáo viên phải sinh bộ ca kiểm thử,
họ sẽ phải cung cấp mã nguồn mẫu (mã nguồn của bài toán tương ứng mà không có
lỗi). Phương pháp này sẽ tự động sinh các ca kiểm thử (bao gồm dữ liệu kiểm thử và
giá trị đầu ra mong muốn tương ứng) từ mã nguồn được giáo viên cung cấp. Sau khi


2
hoàn tất quá trình này, giáo viên sẽ có một bộ dữ liệu kiểm thử bao quát hết các nhánh
của mã nguồn. Tuy nhiên, phương pháp này [2, 3] chỉ cho phép phát hiện những lỗi
tiềm ẩn trong mã nguồn (có đặc tả và được lập trình hoặc không có đặc tả và được lập
trình). Phương pháp này không kiểm tra được các lỗi ứng với tình huống có đặc tả và
không được lập trình (thường được phát hiện bởi các phương pháp kiểm thử hộp đen).
Phương pháp đề xuất trong [2] mới sinh được các dữ liệu kiểm thử, chưa sinh được
đầu ra mong muốn, do đó không hỗ trợ được giáo viên trong việc sinh các ca kiểm thử
mẫu. Trong [3] đã sinh được các ca kiểm thử cho mã nguồn Java nhưng chưa hỗ trợ
xây dựng hệ thống chấm bài.

Mục tiêu của luận văn này là hướng đến nghiên cứu giải pháp và xây dựng bộ
công cụ hỗ trợ giáo viên chấm bài lập trình một cách tự động nhằm giải quyết các vấn
đề như mô tả ở trên. Mấu chốt của giải pháp này là phương pháp sinh dữ liệu kiểm thử
từ mã nguồn. Bản chất của các phương pháp này là phụ thuộc vào ngôn ngữ lập trình
được sử dụng (mỗi ngôn ngữ lập trình thường có kỹ thuật sinh dữ liệu kiểm thử khác
nhau vì chúng ta cần phải phân tích mã nguồn). Mặc dù ngôn ngữ lập trình được dùng
phổ biến nhất trong các trường Trung học phổ thông là Pascal nhưng ngôn ngữ này
chưa có công cụ phân tích cây cú pháp (nền tảng cho việc xây dựng đồ thị dòng điều
khiển). Vì vậy, phương pháp sinh dữ liệu kiểm thử từ mã nguồn Pascal rất khó thực
hiện trong luận văn này. Ngôn ngữ C/C++ đã được quan tâm nghiên cứu với giải pháp
khá tốt trong [2]. Vì vậy, luận văn này tập trung nghiên cứu giải pháp cho ngôn ngữ
Java. Trong [3] đã nghiên cứu giải pháp tương tự cho Java nhưng chỉ dừng lại với các
đơn vị chương trình (hàm, phương thức). Phương pháp này có thể sử dụng khi chương
trình được viết bằng phương pháp hướng đối tượng. Tuy nhiên, học sinh tại các trường
Trung học phổ thông thường viết chương trình theo phương pháp hướng cấu trúc nên
giải pháp này không sử dụng được. Cùng với phương pháp này, luận văn cũng sẽ
nghiên cứu các kỹ thuật kiểm thử hộp đen nhằm sinh bổ sung các ca kiểm thử cho
phương pháp trên. Một công cụ hỗ trợ cũng sẽ được phát triển và thực nghiệm với một
số chương trình đơn giản ở bậc Trung học phổ thông nhằm minh chứng cho kết quả
của luận văn.
Phần còn lại của đề tài nghiên cứu sẽ gồm những nội dung sau. Chương 2 trình
bày tổng quan phương pháp sinh dữ liệu kiểm thử dòng điều khiển từ mã nguồn. Đây
là phương pháp chung, có thể áp dụng cho nhiều ngôn ngữ lập trình khác nhau, trong
chương này cũng đề xuất phương pháp phân tích mã nguồn Java nhằm sinh ca kiểm
thử cho các hàm Java. Chương 3 giới thiệu công cụ hỗ trợ sinh ca kiểm thử tự động và
kết quả thực nghiệm bằng cách áp dụng công cụ, cài đặt với một số chương trình đơn
giản. Cuối cùng, kết luận và các hướng nghiên cứu của luận văn sẽ được mô tả trong
Chương 4.



3

Chƣơng 2: Phƣơng pháp sinh dữ liệu kiểm thử dòng
điều khiển
Chương này trình bày tổng quan về phương pháp kiểm thử dòng điều khiển từ đồ
thị dòng điều khiển (Control Flow Graph - CFG) của chương trình nhằm sinh ca kiểm
thử cho mã nguồn ứng với tiêu chí kiểm thử yêu cầu. Phương pháp trình bày trong
chương này có thể áp dụng cho hầu hết các ngôn ngữ lập trình.

2.1 Tổng quan về kiểm thử dòng điều khiển
Kiểm thử dòng điều khiển là phương pháp kiểm thử hộp trắng nhằm phát hiện
các lỗi tiềm ẩn xảy ra trên mã nguồn [1, 6]. Phương pháp này dựa vào việc phân tích
mã nguồn nhằm xây dựng đồ thị dòng điều khiển ứng với các tiêu chí kiểm thử cho
trước. Dựa vào đồ thị này, một bộ dữ liệu kiểm thử sẽ được sinh ra đáp ứng 100% tiêu
chí kiểm thử yêu cầu. Người sử dụng sẽ sử dụng đặc tả của bài toán để sinh ra các ca
kiểm thử từ bộ dữ liệu kiểm thử đã được sinh ra. Bộ ca kiểm thử này sau đó sẽ được sử
dụng để làm bộ kiểm thử mẫu thực hiện kiểm thử trên bài tập lập trình của học sinh
phục vụ cho quá trình chấm bài.

Mã nguồn
Xây dựng CFG
Tiêu chí kiểm
thử

Sinh đường đi kiểm thử

Sinh dữ liệu kiểm thử

Sinh đầu ra mong muốn


Thực thi ca kiểm thử

Báo cáo kiểm thử

Hình 2.1. Tổng quan quy trình kiểm thử dòng điều khiển


4
Quy trình kiểm thử dòng điều khiển của một hàm được mô tả như Hình 2.1. Đầu
vào của quy trình là mã nguồn và tiêu chí kiểm thử yêu cầu. Đầu ra của quy trình là
báo cáo kiểm thử chứa các kết quả kiểm thử (ca kiểm thử nào phát hiện được lỗi và ca
kiểm thử nào không phát hiện được lỗi). Chi tiết phương pháp bao gồm các bước sau:
- Bước 1: Sinh đồ thị dòng điều khiển. Mã nguồn được phân tích dựa trên các tiêu chí
kiểm thử để xây dựng đồ thị dòng điều khiển. Với mỗi tiêu chí kiểm thử là phủ câu
lệnh, phủ nhánh và phủ điều kiện con, sẽ có một đồ thị dòng điều khiển tương ứng.
- Bước 2: Sinh các đường đi kiểm thử. Từ đồ thị dòng điều khiển, luận văn đề xuất
thuật toán duyệt đồ thị sao cho các đường đi kiểm thử được sinh ra đạt độ phủ thỏa
mãn các tiêu chí đã đề ra.
- Bước 3: Sinh ca kiểm thử. Ca kiểm thử bao gồm bộ giá trị đầu vào được chọn để
thực hiện kiểm thử trên mỗi đường đi và giá trị đầu ra mong muốn tương ứng
(Expected Output – EO). Ca kiểm thử được sinh ra bằng cách các hệ ràng buộc trên
mỗi đường kiểm thử. Giá trị đầu ra mong muốn được sinh từ đặc tả bài toán. Kết
thúc bước này, một tập các ca kiểm thử được sinh ra.
- Bước 4: Thực thi các ca kiểm thử. Thực thi các ca kiểm thử nhằm tạo ra báo cáo
kiểm thử trong đó chỉ ra ca kiểm thử nào phát hiện được lỗi, ca kiểm thử nào không
phát hiện được lỗi.

2.2 Các tiêu chí kiểm thử
Tiêu chí kiểm thử là chuẩn mực để đánh giá độ bao phủ của một tập ca kiểm thử
so với mã nguồn. Nhằm tối ưu các ca kiểm thử, tiêu chí kiểm thử được đưa ra để thiết

kế các ca kiểm thử sao cho số ca kiểm thử là ít nhất những vẫn có thể kiểm tra được tối
đa các trường hợp (có thể mắc lỗi) xảy ra trên mã nguồn. Các thành phần cần kiểm tra
bao gồm câu lệnh, các đỉnh quyết định, các điều kiện con, đường thi thành hoặc sự kết
hợp giữa chúng [1].
Có rất nhiều tiêu chí kiểm thử được áp dụng trong thực tế, dưới đây là ba tiêu chí
kiếm thử đang được sử dụng rộng rãi [1, 2]:
-

Phủ câu lệnh: Sau khi thực hiện các ca kiểm thử, mỗi dòng lệnh trên mã nguồn
phải được duyệt qua ít nhất một lần. Giả sử, ta cần sinh các ca kiểm thử cho hàm
laNamNhuan có mã nguồn được hiển thị ở Hình 2.2. Để đạt được 100% tiêu chí
phủ câu lệnh cho hàm, ta cần thực hiện ba ca kiểm thử như Bảng 2.1. Giá trị EO
(Expected Output) trên bảng là giá trị đầu ra mong muốn khi chạy ca kiểm thử,
RO (Real Output) là giá trị đầu ra thực tế (giá trị này sẽ được điền khi chạy các ca
kiểm thử trong môi trường thực).


5
public int laNamNhuan(int year) {
if(year<0)
return -1;
if((year%400==0)||((year%4==0)&&(year%100!=0)))
return 1;
else
return 0;
}

Hình 2.2. Mã nguồn hàm laNamNhuan

Bảng 2.1. Các ca kiểm thử cho tiêu chí phủ câu lệnh của hàm laNamNhuan


STT
Tc1
Tc2
Tc3
-

Input
-2000
2000
2001

EO
-1
1
0

RO

Phủ nhánh: Sau khi thực hiện ca kiểm thử, các điểm quyết định trên mã nguồn
được duyệt theo cả hai nhánh đúng và sai. Ví dụ, với hàm laNamNhuan, để đạt
được 100% tiêu chí phủ nhánh, ta cần thực hiện các ca kiểm thử để kiểm tra các
điều kiện như Bảng 2.2 để các điểm quyết định ở câu lệnh 1 và câu lệnh 3 được
duyệt qua cả hai nhánh đúng và sai.
Bảng 2.2. Các trƣờng hợp cần kiểm thử với tiêu chí phủ nhánh cho hàm laNamNhuan

Điểm quyết
định
1
3


Điều kiện

Đúng

Sai

Year <0

Tc1

Tc2

(year%400==0)||((year%4==0)&&(year
%100!=0))

Tc2

Tc3

Hàm laNamNhuan là một trường hợp đặc biệt, ba ca kiểm thử thỏa mãn tiêu chí
phủ câu lệnh cũng đồng thời thỏa mãn tiêu chí phủ nhánh. Trong nhiều trường hợp
khác, số ca kiểm thử ứng với tiêu chí phủ nhánh thường nhiều hơn số ca kiểm thử của
tiêu chí phủ câu lệnh do các ca kiểm thử của tiêu chí phủ câu lệnh không phủ được hết
các nhánh đúng và sai trên mã nguồn.
-

Phủ điều kiện con: Với các điểm quyết định có chứa điều kiện phức hợp (từ hai
điều kiện con trở lên), sau khi thực hiện các ca kiểm thử, tất cả các điều kiện con
đều được duyệt qua cả hai nhánh đúng và sai. Ví dụ, trong câu lệnh 3 của hàm

laNamNhuan có chứa điều kiện phức hợp là (year%400==0)||
((year%4==0)&&(year%100!=0)). Nếu chỉ thực hiện kiểm thử với tiêu chí phủ


6
nhánh thì chỉ có điều kiện (year%400==0)được kiểm tra, còn hai điều kiện con
(year%4==0) và (year%100!=0) thì chưa được kiểm tra tới. Chúng ta cần phải
kiểm tra tất cả các nhánh trên các điều kiện trên mã nguồn thì mới đạt được tiêu
chí phủ điều kiện con. Bảng 2.3 là các trường hợp cần kiểm tra để mọi điều kiện
con trên hàm laNamNhuan đều được "ghé thăm".
Bảng 2.3. Các trƣờng hợp cần kiểm thử với tiêu chí phủ điều kiện con của hàm
laNamNhuan

Đỉnh quyết
định
1
3
3
3
3

Điều kiện

Đúng

Sai

Year<0

Tc1

Tc2
?
?
?

Tc2
Tc3
?
?
?

year%400==0
(Year%4==0)&&(year%100!=0)
year%4==0
year%100!=0

Rõ ràng, các ca kiểm thử ứng với tiêu chí phủ nhánh chỉ kiểm thử được 3/6 ca
kiểm thử (tương ứng với độ phủ đạt 50%) của tiêu chí phủ điều kiện con. Để kiểm tra
tất cả các điểm quyết định cho hàm laNamNhuan, ta cần thực hiện sáu ca kiểm thử
như Bảng 2.4.
Bảng 2.4. Các ca kiểm thử cho tiêu chí phủ điều kiện con của hàm laNamNhuan

STT

Input

EO

Tc1
Tc2

Tc3
Tc4
Tc5
Tc6

-1
2000
1996
1997
1900
2200

-1
1
1
0
0
0

RO

2.3 Xây dựng đồ thị dòng điều khiển
Đồ thị dòng điều khiển (CFG) là một phần rất quan trọng trong phương pháp
kiểm thử dòng điều khiển. CFG mô tả cấu trúc của mã nguồn thông qua một đồ thị có
hướng với mỗi đỉnh tương ứng là một câu lệnh/nhóm lệnh. CFG cho người dùng quan
sát một cách trực quan các luồng điều khiển của mã nguồn. Từ đó, chúng ta dễ dàng
thiết kế các ca kiểm thử sao cho nó phủ hết các nhánh trên đồ thị này.
Để xây dựng được CFG từ mã nguồn, ta quy ước mỗi câu lệnh/ nhóm lệnh trên
mã nguồn tương ứng là một đỉnh của đồ thị. Nếu một câu lệnh j thực hiện ngay sau câu



7
lệnh i thì sẽ tồn tại một đường đi từ đỉnh i đến đỉnh j. Mỗi tiêu chí kiểm thử, chúng ta
xây dựng được một CFG tương ứng [1].
Một CFG được xây dựng từ đỉnh bắt đầu (ứng lời khai báo hàm), đi qua các đỉnh
(các câu lệnh khai báo, câu lệnh gán, câu lệnh điều kiện, câu lệnh lặp, các khối xử lý...)
theo thứ tự thực hiện trên mã nguồn và đi đến đỉnh kết thúc (ứng với điểm kết thúc
hàm). Các thành phần để xây dựng CFG được mô tả ở Hình 2.3. [1]

Đỉnh bắt đầu

Đỉnh xử


Đỉnh quyết
định

Đỉnh kết
thúc

Đỉnh
nối

Hình 2.3. Các thành phần cơ bản của đồ thị dòng điều khiển

Ngoài đỉnh bắt đầu và đỉnh kết thúc, mỗi đỉnh là duy nhất trong đồ thị, các đỉnh
khác trong đồ thị tương ứng với một câu lệnh của mã nguồn, được đặt tên theo chức
năng của câu lệnh. Đỉnh xử lý ứng với câu lệnh khai báo, gán giá trị hoặc các câu lệnh
tính toán. Đỉnh quyết định ứng với câu lệnh rẽ nhánh hoặc biểu thức điều kiện trong
câu lệnh lặp. Đỉnh nối là đỉnh tiếp theo được thực hiện ngay sau khi câu lệnh rẽ nhánh

hoặc lặp kết thúc [1, 2, 6].
Trong Java, các cấu trúc điều khiển bao gồm: cấu trúc tuần tự, cấu trúc rẽ nhánh
if…else, cấu trúc rẽ nhánh switch...case, các cấu trúc lặp while...do, do...while. Riêng
vòng lặp for, chúng ta sử dụng cấu trúc while...do để thay thế (vì for là một trường hợp
đặc biệt của while...do với số lần lặp biết trước). Các ký hiệu đại diện cho mỗi cấu trúc
điều khiển được minh họa trên Hình 2.4 [1, 2]. Chúng ta sẽ sử dụng các thành phần và
cấu trúc ở Hình 2.3, Hình 2.4 cùng với các tiêu chí kiểm thử để xây dựng đồ thị dòng
điều khiển cho mã nguồn.

C

Cấu trúc tuần
tự

Cấu trúc
if…esle

C

Cấu trúc
while...do

C

C

Cấu trúc
do...while

Cấu trúc

switch…case

Hình 2.4. Các cấu trúc điều khiển cơ bản của đồ thị dòng điều khiển


8

2.3.1 Xây dựng đồ thị dòng điều khiển ứng với tiêu chí phủ câu lệnh và
phủ nhánh
Chúng ta sẽ thực hiện xây dựng CFG từ mã nguồn theo các bước như sau: Đầu
tiên, ta đánh số thứ tự cho các câu lệnh trên mã nguồn. Từ đỉnh bắt đầu ứng với lời gọi
hàm ta lần lượt nối các đỉnh theo thứ tự thực hiện câu lệnh trên mã nguồn. [1, 2]. Do
tiêu chí phủ câu lệnh và phủ nhánh có các đường đi phủ toàn bộ các câu lệnh trên mã
nguồn, nên CFG của hai tiêu chí này có hình dạng giống nhau. CFG của tiêu chí phủ
điều kiện con có cấu trúc phức tạp hơn do các đường đi trên đồ thị này phủ đến cả hai
nhánh của các điều kiện con cơ bản.
public int laNamNhuan(int year) {
1. if(year<0)
2.
return -1;
3. if((year%400==0)||((year%4==0)&&(year%100!=0)))
4.
return 1;
else
5.
return 0;

T

1

F

2
3

T
4
5

}

a)

b)

Hình 2.5. Mã nguồn và CFG ứng với tiêu chí phủ câu lệnh của hàm laNamNhuan

Giả sử, chúng ta xây dựng CFG ứng với tiêu chí phủ câu lệnh và phủ nhánh của
hàm laNamNhuan có mã nguồn như Hình 2.5a. Các câu lệnh được đánh số thứ tự cũng
đồng thời là các đỉnh của đồ thị. Đỉnh bắt đầu của đồ thị tương ứng với lời gọi hàm.
Đỉnh 1 là đỉnh quyết định tương ứng với câu lệnh 1. Đỉnh 2 là đỉnh xử lý ứng với câu
lệnh 2 (return -1). Nếu điều kiện tại đỉnh 1 (year<0) là đúng thì tồn tại đường đi
nối đỉnh 1 với đỉnh 2 rồi đi đến đỉnh kết thúc. Ngược lại, nếu điều kiện tại đỉnh 1
(year<0) là sai thì đường đi sẽ nối từ đỉnh 1 tới đỉnh 3 tương ứng với câu lệnh 3
(year%400==0) || ((year%4==0) && (year%100!=0)). Đỉnh 3 là đỉnh quyết định
nên nếu điều kiện tại đỉnh 3 là đúng thì tồn tại đường đi nối đỉnh 3 với đỉnh 4 ứng với
câu lệnh 4 (return 1) rồi nối đỉnh 4 đến đỉnh kết thúc. Ngược lại, nếu điều kiện tại
đỉnh 3 là sai thì đường đi sẽ nối đỉnh 3 đến đỉnh 5 tương ứng với câu lệnh 5 (return
0) rồi nối đỉnh 5 đến đỉnh kết thúc. Cuối cùng, ta dựng được đồ thị dòng điều khiển
của hàm laNamNhuan thỏa mãn phủ toàn bộ các câu lệnh trên mã nguồn như Hình

2.5b. Đây chính là CFG cho tiêu chí phủ câu lệnh và cũng là CFG cho tiêu chí phủ
nhánh.


9

2.3.2 Xây dựng CFG ứng với tiêu chí phủ điều kiện con
Trên các mã nguồn có chứa câu lệnh mang điều kiện phức hợp, chúng ta cần xây
dựng CFG ứng với tiêu chí phủ điều kiện con. Các điều kiện con thuộc điều kiện phức
hợp sẽ được tách các đỉnh con tương ứng trên CFG. Cách xây dựng CFG với tiêu chí
phủ điều kiện con cũng tương tự như xây dựng CFG ứng với tiêu chí phủ câu lệnh.
public int laNamNhuan(int year) {
1.
if(year<0)
2.
return -1;
if((year%400==0)||((year%4==0)&&(year%100!=0)))
3a
3b
3c
4.
return 1;
else
5.
return 0;

1
T
3a
2


F

T

3b
F

F
5

}

a)

T
3c
T

4

b)

Hình 2.6. Mã nguồn và CFG ứng với tiêu chí phủ điều kiện con của hàm laNamNhuan

Ví dụ, ta cần xây dựng CFG với tiêu chí phủ điều kiện con của hàm laNamNhuan
như Hình 2.6a. Trên mã nguồn, câu lệnh 3 chứa ba điều kiện con là
(year%400==0);(year%4==0) và (year%100!=0) nên ta tách đỉnh 3 thành các đỉnh
con 3a, 3b, 3c. Đỉnh 1 là đỉnh quyết định, ứng với câu lệnh 1. Nếu điều kiện tại đỉnh 1
(year<0) là đúng thì tồn tại đường đi nối đỉnh 1 với đỉnh 2 tương ứng với câu lệnh 2

(return -1) rồi nối đến đỉnh kết thúc. Nếu điều kiện tại đỉnh 1 (year<0) là sai thì
đường đi sẽ nối đỉnh 1 với đỉnh 3a (year%400==0). Từ câu lệnh 3, toán tử kết hợp
giữa điều kiện con 3a và điều kiện con 3b, 3c là toán tử hoặc "||". Do đó, nếu điều
kiện tại đỉnh 3a(year%400==0) là đúng thì ta không cần xét đến các điều kiện còn lại.
Ta sẽ có đường đi nối đỉnh 3a với đỉnh 4(return 1) rồi nối đến đỉnh kết thúc.
Ngược lại, nếu điều kiện tại đỉnh 3a là sai thì ta cần xét tiếp các điều kiện tại đỉnh 3b
(year%4==0) và 3c (year%100!=0), ta có đường đi nối từ đỉnh 3a với 3b theo nhánh
sai của đỉnh 3a. Toán tử kết hợp giữa điều kiện con 3b (year%4==0) và 3c
(year%100!=0) là toán tử "&&", nên nếu điều kiện tại hai đỉnh 3b và 3c là đúng thì ta
có đường đi nối các đỉnh 3a(T), 3b(T)và nối với đỉnh 4 (return 1) rồi đi đến đỉnh
kết thúc. Nếu một trong hai điều kiện tại đỉnh 3a (year%4==0) hoặc 3b
(year%100!=0) là sai thì đường đi sẽ nối một trong hai đỉnh theo nhánh sai của 3a và
3b nối với đỉnh 5(return 0) rồi nối đỉnh 5 đến đỉnh kết thúc. Cuối cùng, ta dựng
được CFG ứng với tiêu chí phủ điều kiện con của hàm như Hình 2.6b.


10

2.3.3 Phƣơng pháp xây dựng CFG từ mã nguồn Java
Để xây dựng CFG từ mã nguồn cho mã nguồn Java trong môi trường thực, chúng
ta cần có cấu trúc dữ liệu của mã nguồn tương ứng. Cấu trúc này thường được sinh ra
bằng cách sử dụng công cụ hỗ trợ JDT (Java Development Tooling). Công cụ này sẽ
phân tích các hàm đầu vào thành các cây cú pháp trừu tượng (Abstract Syntax Tree –
AST). Trong bước này, phương pháp tập trung vào việc lấy được danh sách các khai
báo hàm số có trong mã nguồn, sử dụng theo API của plugin JDT [3]. Khi có được cây
AST, chúng ta tiến hành phân tích cây cú pháp trừu tượng để xây dựng CFG cho mã
nguồn Java. Cuối cùng, chuẩn hóa định dạng các biểu thức trong cây cú pháp trừu
tượng để phục vụ cho việc phân tích và quản lý.
2.3.3.1 Phân tích mã nguồn
Cây cú pháp trừu tượng (AST) là một cấu trúc mô tả mối quan hệ giữa các thành

phần trên mã nguồn. Trên cây AST, một lớp (class) bao gồm các thành phần như sau:
-

Định nghĩa lớp: Là nút bao gồm các nút con về phạm vi truy cập (public, private,
v.v.), tên lớp và thân lớp. Phần thân lớp gồm các nút khai báo thuộc tính và các nút
định nghĩa hành vi (phương thức).

-

Khai báo biến: Mỗi nút là một thuộc tính của lớp với các nút con về phạm vi truy
cập (public, private, v.v.), kiểudữ liệu và danh sách tên biến. Ví dụ: câu lệnh
“private int a, b=10;” bao gồm các thông tin về phạm vi truy cập private, kiểu dữ
liệu int, danh sách các biến là a và b=10.

-

Định nghĩa phương thức: là một cây AST con bao gồm các thành phần: định nghĩa
phương thức, khai báo hằng số, biến toàn cục/cục bộ, struct, các câu lệnh trong
thân hàm, v.v. được thể hiện theo quan hệ cha - con. Mỗi AST của một phương
thức sẽ có cấu trúc như sau:
o Tên phương thức: Tên được sử dụng để tìm kiếm một phương thức khi nó
được gọi (invoke) trong một câu lệnh ở thân một phương thức khác.
o Kiểu trả về: Được sử dụng để sinh loại dữ liệu đầu ra.
o Danh sách đối số: Dùng để xác định chính xác phương thức cần gọi tới trong
trường hợp có nhiều hàm trùng tên.
o Phần thân phương thức: là một cây AST con tương ứng với từng câu lệnh và
các biểu thức tương ứng trên trong.


11

2.3.3.2 Xây dựng CFG từ cây cấu trúc trừu tƣợng.
Từ cấu trúc cây AST, chúng ta sử dụng một thuật toán để biến đổi cây AST sang
dạng đồ thị dòng điều khiển, được mô tả ở Thuật toán 2.1.
Thuật toán 2.1: Sinh_G(AST, t)
Đầu vào: AST: cây AST môt tả cấu trúc của hàm cần kiểm thử;
t: tiêu chí kiểm thử
Đầu ra: G: đồ thị dòng điều khiển ứng với độ phủ t,

G là biến toàn cục được khởi tạo là rỗng
1:

for (mỗi nút c trên cây AST)

2:

if (c là đỉnh quyết định)

3:

node := đỉnh đại diện cho c

4:

Cập nhật node vào G

5:

Liên kết node với các đỉnh của G

6:


T_AST := các đỉnh thuộc cây AST theo nhánh đúng

7:

Sinh_G(T_AST, t)

8:

F_AST :=các đỉnh thuộc cây AST theo nhánh sai

9:

Sinh_G(F_ AST, t)

10:

elseif(c là các câu lệnh break, continue, return, goto ...)

11:

N_ AST := đỉnh liên kết tiếp theo sau c thuộc cây AST

12:

Sinh_G(N_ AST, t)

13:

elseif (c là nhóm lệnh)


14:

c_AST :=cây AST của nhóm lệnh c

15:

Sinh_G(c, t)

16:

else

17:

node := đỉnh đại diện cho c

18:

cập nhật node vào G

19:

Liên kết node với các đỉnh của G

20:

endif

21:


endfor

L
L


12
Đầu vào của thuật toán là cây AST môt tả cấu trúc mã nguồn và tiêu chí kiểm thử
t. Đầu ra của thuật toán là một đồ thị G mô tả dòng điều khiển của mã nguồn.
Đầu tiên, với từng nút c của cây AST được duyệt theo thứ tự top-down (dòng 1).
Nếu nút c là đỉnh quyết định (dòng 2) (if…else, for, do…while, v.v.) thì tạo một node
mới của G tương ứng với nút c trên cây AST và cập nhật node vào G (dòng 3, 4). Tiếp
theo, liên kết node với các đỉnh khác trong đồ thị G (dòng 5). Sau đó, gọi đệ quy (dòng
7, 9) cây AST là T_AST và F_AST của các khối lệnh ứng với nhánh đúng vào nhánh
sai (dòng 6, 8). Nếu c là các từ khóa (return, break, continue, …) thì cây AST N_AST
được gọi đệ quy (dòng 11, 12). Còn nếu c là một khối các câu lệnh thì cây AST c_AST
của c được gọi đệ quy (dòng 14, 15). Nếu c là câu lệnh gán hoặc khai báo thì thì một
đỉnh node mới của G được khởi tạo đại diện cho c và thêm các liên kết với các đỉnh
khác trong đồ thị (dòng 17, 18, 19). Thuật toán kết thúc khi nút cuối cùng của cây
AST được duyệt, ta dựng được đồ thị G mô tả cấu trúc điều khiển của mã nguồn Java.

2.4 Sinh đƣờng đi kiểm thử từ đồ thị
Đường đi xuất phát từ đỉnh bắt đầu của CFG, đi qua các đỉnh trong đồ thị theo
thứ tự thực hiện câu lệnh đến đỉnh kết thúc được gọi là một đường đi độc lập. Một tập
đường đi độc lập trên đồ thị thỏa mãn các tiêu chí kiểm thử gọi là tập đường kiểm thử.
Mục tiêu của quá trình sinh các đường kiểm thử là tìm được số đường kiểm thử ít nhất
nhưng đạt được độ phủ tối đa trên đồ thị.
Trên mỗi CFG, tập đường kiểm thử được xác định sao cho nó phủ hết các nhánh
của đồ thị. Theo [7], số đường đi của chương trình ứng với đồ thị dòng điều khiển của

nó được tính bằng số đỉnh quyết định của CFG tương ứng cộng 1 hoặc bằng số cạnh
trừ số đỉnh của CFG tương ứng cộng 2.

2.4.1 Sinh đƣờng đi thỏa mãn tiêu chí phủ câu lệnh
Để sinh các đường kiểm thử thỏa mãn tiêu chí phủ câu lệnh từ CFG tương ứng,
chúng ta tìm các đường đi sao cho mỗi đỉnh được "ghé thăm" ít nhất một lần (đồng
nghĩa với mỗi câu lệnh được duyệt qua ít nhất một lần).
Ví dụ, ta cần sinh đường kiểm thử thỏa mãn tiêu chí phủ câu lệnh cho hàm
laNamNhuan có CFG được hiển thị ở Hình 2.7. Trên đồ thị, ta xác định được ba
đường đi để mỗi đỉnh của đồ thị được đi qua ít nhất một lần, các đường được liệt kê
như sau:
p1: 1(T), 2
p2: 1(F), 3(T), 4
p3: 1(F), 3(F), 5


×