Tổng quan nghiên cứu

Trong quy trình phát triển phần mềm hiện đại, chi phí dành cho kiểm thử hộp trắng mức đơn vị thường chiếm từ 50% đến hơn 60% tổng ngân sách toàn dự án. Đối với các hệ sinh thái phần mềm công nghiệp và hệ thống nhúng phát triển bằng ngôn ngữ C/C++, số lượng hàm cần kiểm thử thường lên tới hàng nghìn hoặc thậm chí hàng chục nghìn hàm, khiến việc kiểm thử thủ công trở thành nút thắt cổ chai làm chậm tiến độ bàn giao sản phẩm. Luận văn thạc sĩ chuyên ngành Kỹ thuật phần mềm của tác giả Nguyễn Đức Anh tại Trường Đại học Công nghệ, Đại học Quốc gia Hà Nội năm 2017 đã giải quyết triệt để bài toán tự động hóa kiểm thử mã nguồn C/C++. Mục tiêu trọng tâm của nghiên cứu là xây dựng phương pháp phân tích cú pháp kết hợp thực thi tượng trưng để sinh dữ liệu kiểm thử định hướng đạt độ phủ tối đa với số lượng ca kiểm thử nhỏ nhất. Nghiên cứu được triển khai thực nghiệm toàn diện trong giai đoạn 2015 đến 2017 trên các tập mã nguồn C/C++ đa dạng cấu trúc. Ý nghĩa thực tiễn của công trình thể hiện rõ nét qua việc rút ngắn thời gian sinh dữ liệu kiểm thử xuống chỉ còn khoảng 5 giây cho các cấu trúc điều kiện phức tạp, đồng thời đảm bảo tỷ lệ bao phủ nhánh và câu lệnh đạt tuyệt đối 100%, giúp doanh nghiệp phần mềm giảm thiểu tối đa gánh nặng lưu trữ và bảo trì các bộ kiểm thử dư thừa.

Cơ sở lý thuyết và phương pháp nghiên cứu

Khung lý thuyết áp dụng

Nghiên cứu được xây dựng dựa trên nền tảng lý thuyết kiểm thử tự động định hướng kết hợp thực thi tượng trưng động được khởi xướng bởi Koushik Sen từ năm 2005. Khung lý thuyết của luận văn tích hợp ba trụ cột chính: Đồ thị dòng điều khiển biểu diễn luồng thực thi của hàm, Cây cú pháp trừu tượng mô hình hóa ngữ pháp ngôn ngữ C/C++, và Hệ ràng buộc đường thi hành. Để mô phỏng chính xác hành vi của mã nguồn C/C++, tác giả xây dựng mô hình bộ nhớ trừu tượng gồm ba thành phần tương tác chặt chẽ: bảng biến lưu trữ thông tin phạm vi cùng định danh, bộ nhớ logic mô phỏng cấu trúc cấp phát động của con trỏ và mảng, cùng bộ nhớ vật lý quản lý giá trị của các ô nhớ cơ bản. Nghiên cứu áp dụng ba tiêu chí đánh giá độ phủ tiêu chuẩn gồm độ phủ câu lệnh, độ phủ nhánh và độ phủ điều kiện biến đổi cấp ba. Luận văn cũng vận dụng lý thuyết thỏa mãn mệnh đề modulo kết hợp bộ giải Z3 và định dạng biểu thức SMT-Lib 2.0 nhằm tự động hóa quá trình giải hệ ràng buộc để tìm nghiệm dữ liệu đầu vào.

Phương pháp nghiên cứu

Để kiểm chứng tính đúng đắn và hiệu năng của giải pháp, tác giả thiết lập cỡ mẫu thực nghiệm gồm 21 hàm kiểm thử chuẩn mức đơn vị thu thập từ các kho mã nguồn mở uy tín trên GitHub và tập dự án kiểm chuẩn do Trung tâm Nghiên cứu và Phát triển Công nghệ Toshiba Việt Nam cung cấp. Phương pháp chọn mẫu tập trung vào các đoạn mã nguồn C/C++ điển hình chứa cấu trúc vòng lặp phức tạp, lời gọi đệ quy, con trỏ cấu trúc và cấu trúc phân nhánh đa tầng với chỉ số phức tạp điều khiển McCabe dao động từ 2 đến 7. Nghiên cứu sử dụng phương pháp phân tích thực nghiệm so sánh định lượng trực tiếp giữa công cụ tự phát triển với 4 công cụ kiểm thử tự động hàng đầu thế giới gồm KLEE, PathCrawler, CAUT và CREST. Phương pháp này được lựa chọn vì cho phép đánh giá khách quan các chỉ số then chốt như số lượng ca kiểm thử sinh ra, tỷ lệ độ phủ đạt được và thời gian thực thi. Toàn bộ quá trình nghiên cứu, mô hình hóa toán học và thực nghiệm được tiến hành liên tục trong thời gian 24 tháng, mang lại những kết quả khoa học giá trị được công bố tại hai hội nghị quốc tế NICS 2016 và SoICT 2017.

Kết quả nghiên cứu và thảo luận

Những phát hiện chính

Kết quả thực nghiệm trên công cụ tự phát triển mang tên CFT4Cpp đã chứng minh tính ưu việt vượt trội so với các công cụ quốc tế trên toàn bộ 21 bài kiểm tra thực tế:

  • Về số lượng bộ dữ liệu kiểm thử sinh ra, đối với hàm kiểm tra biến chưa khởi tạo, công cụ đề xuất chỉ cần tạo đúng 5 bộ dữ liệu để đạt 100% độ phủ nhánh, trong khi công cụ KLEE phải sinh tới 27 bộ dữ liệu và PathCrawler cần hơn 20 bộ dữ liệu.
  • Đối với hàm so sánh mảng ký tự và con trỏ phức tạp, công cụ đề xuất đạt 100% độ phủ chỉ với 3 ca kiểm thử, vượt bậc so với KLEE khi sinh tới 82 ca kiểm thử và PathCrawler chỉ đạt độ phủ 16,67% với 1 ca duy nhất.
  • Trong bài toán kiểm thử cấu trúc vòng lặp và đệ quy, thuật toán duyệt ưu tiên số lần lặp nhỏ đã giúp 100% các hàm kiểm thử đạt độ phủ tối đa mà không bị rơi vào trạng thái bùng nổ đường thi hành hoặc tràn bộ nhớ.
  • Về mặt tối ưu hóa hạ tầng biên dịch, giải pháp xây dựng bộ thực thi tổng quát đã giảm thiểu thời gian thực thi từ N lần biên dịch riêng lẻ xuống còn duy nhất 1 lần biên dịch cho toàn bộ tập dữ liệu, tiết kiệm hơn 70% tổng thời gian kiểm thử tự động.

Thảo luận kết quả

Dữ liệu thực nghiệm khi được tổng hợp qua bảng so sánh tỷ lệ độ phủ và biểu đồ cột biểu diễn số lượng ca kiểm thử cho thấy sự khác biệt rõ nét giữa các phương pháp tiếp cận. Nguyên nhân công cụ KLEE sinh ra số lượng ca kiểm thử quá lớn là do công cụ này áp dụng kỹ thuật thực thi sinh kiểm thử nhằm mục tiêu kép vừa tìm lỗi vừa phủ mã nguồn, dẫn đến việc phân nhánh tiến trình quá mức và kiểm tra mọi kịch bản thực thi. Trong khi đó, các công cụ như PathCrawler và CAUT thường bị lỗi dừng sớm hoặc thất bại trong việc sinh dữ liệu kiểm thử đầu tiên cho các hàm có con trỏ cấu trúc do phụ thuộc vào cơ chế sinh ngẫu nhiên. Công cụ đề xuất đã giải quyết triệt để hạn chế này nhờ pha tiền xử lý mã nguồn, xây dựng cây cấu trúc dự án và chèn câu lệnh đánh dấu thông minh. Hơn nữa, việc tích hợp kỹ thuật giải hệ ràng buộc tăng dần cùng cơ chế kiểm tra tính thỏa mãn dựa trên bộ nhớ đệm đã giúp giảm tải hơn 40% thời gian tính toán của bộ giải Z3.

Đề xuất và khuyến nghị

Dựa trên các phát hiện thực nghiệm, luận văn đưa ra 4 khuyến nghị hành động cụ thể nhằm nâng cao hiệu quả kiểm thử phần mềm C/C++:

  • Tích hợp công cụ phân tích mã nguồn tự động vào quy trình phát triển phần mềm nhúng, hướng tới mục tiêu cắt giảm 50% chi phí và thời gian kiểm thử đơn vị trong vòng 6 tháng đầu triển khai, do các kỹ sư đảm bảo chất lượng phần mềm trực tiếp chủ trì thực hiện.
  • Áp dụng thuật toán chọn đường thi hành ưu tiên số lần lặp nhỏ kết hợp mô hình bộ nhớ tượng trưng nhằm tối ưu hóa số lượng ca kiểm thử, duy trì tỷ lệ độ phủ nhánh trên 95% trong lộ trình 3 tháng cho toàn bộ dự án C/C++, chịu trách nhiệm bởi các trưởng nhóm kỹ thuật.
  • Mở rộng năng lực phân tích mã nguồn của công cụ để hỗ trợ toàn diện các đặc tính nâng cao của ngôn ngữ C++ hiện đại như cấu trúc lập trình mẫu tổng quát và các lớp trong thư viện chuẩn, hoàn thiện hệ thống trong thời hạn 12 tháng, do các nhóm nghiên cứu tại viện và trường đại học đảm nhiệm.
  • Chuẩn hóa đầu ra của quy trình sinh dữ liệu kiểm thử tự động sang khung kiểm thử Google Test và biên bản định dạng bảng tính, giúp tăng tốc độ đánh giá và kiểm tra mã nguồn lên 30% trong vòng 6 tháng, do các chuyên gia tự động hóa quy trình phần mềm phụ trách.

Đối tượng nên tham khảo luận văn

Luận văn là nguồn tư liệu chuyên sâu mang lại giá trị thiết thực cho 4 nhóm đối tượng trọng tâm:

  • Kỹ sư kiểm thử phần mềm và chuyên viên tự động hóa kiểm thử: Nắm bắt phương pháp sinh ca kiểm thử tự động đạt độ phủ cao, ứng dụng xuất tự động mã nguồn kiểm thử chuẩn Google Test, loại bỏ hoàn toàn thao tác viết mã kiểm thử thủ công cho hàng nghìn hàm.
  • Kỹ sư phát triển phần mềm nhúng và hệ thống C/C++: Hiểu rõ cơ chế phân tích luồng điều khiển và quản lý mô hình bộ nhớ con trỏ, từ đó xây dựng mã nguồn chuẩn mực, hạn chế tối đa các lỗi tiềm ẩn như chia cho 0 hay truy cập con trỏ rỗng.
  • Giảng viên, học viên cao học và nghiên cứu viên ngành Công nghệ thông tin: Khai thác tài liệu nghiên cứu học thuật chuẩn mực về phân tích mã nguồn tĩnh, thực thi tượng trưng động và ứng dụng của các bộ giải thỏa mãn lý thuyết modulo trong công nghệ phần mềm.
  • Trưởng dự án và Giám đốc kỹ thuật tại các doanh nghiệp công nghệ: Hoạch định chiến lược tối ưu hóa ngân sách dự án, ứng dụng các giải pháp tự động hóa kiểm thử tiên tiến để tiết kiệm từ 30% đến 50% tổng chi phí phát triển phần mềm quy mô lớn.

Câu hỏi thường gặp

  • Kỹ thuật kiểm thử tự động định hướng trong luận văn xử lý biến con trỏ như thế nào?
    Phương pháp sử dụng mô hình bộ nhớ trừu tượng kết hợp bộ nhớ logic và bảng biến, tự động bổ sung ràng buộc kích thước cấp phát vùng nhớ lớn hơn hoặc bằng 0 và giá trị con trỏ khác rỗng. Nhờ đó, dữ liệu kiểm thử đầu tiên luôn hợp lệ, ngăn chặn 100% nguy cơ chương trình bị sập ngay từ lần chạy thử nghiệm đầu tiên.

  • Tại sao công cụ đề xuất sinh ra ít ca kiểm thử hơn hẳn so với công cụ KLEE?
    Công cụ KLEE áp dụng kỹ thuật thực thi sinh kiểm thử nhằm tìm kiếm mọi trạng thái lỗi tiềm ẩn, khiến số ca kiểm thử tăng vọt lên tới 82 ca cho một hàm ngắn. Ngược lại, thuật toán đề xuất chỉ tập trung chọn các đường thi hành chưa được viếng thăm để tối đa hóa độ phủ, giúp giảm số ca kiểm thử xuống chỉ còn từ 2 đến 5 bộ dữ liệu.

  • Cơ chế biên dịch tổng quát cải thiện tốc độ thực thi kiểm thử như thế nào?
    Thay vì phải tạo mã nguồn và biên dịch riêng biệt N lần cho N bộ dữ liệu kiểm thử theo cách truyền thống, hệ thống xây dựng một bộ thực thi ca kiểm thử tổng quát duy nhất. Toàn bộ dữ liệu kiểm thử được nạp tự động qua tệp dữ liệu ngoài, rút ngắn quy trình xuống 1 lần biên dịch duy nhất và tiết kiệm trên 70% thời gian thực thi.

  • Thuật toán LDFS giải quyết nguy cơ lặp vô hạn trong phân tích mã nguồn ra sao?
    Thuật toán LDFS khởi tạo việc sinh dữ liệu kiểm thử với số lần lặp bằng 1 để bao phủ cả hai nhánh đúng và sai của vòng lặp, sau đó mới duyệt qua số lần lặp 0, 2 và tối đa theo cấu hình. Cách tiếp cận này giúp đạt độ phủ nhánh 100% nhanh chóng mà không cần duyệt toàn bộ số lần lặp lớn của các khối lệnh điều khiển.

  • Kết quả kiểm thử tự động có dễ dàng tích hợp vào dự án phần mềm thực tế không?
    Hệ thống hỗ trợ xuất tự động mã nguồn kiểm thử tương thích hoàn toàn với khung kiểm thử Google Test và biên bản kết quả dạng bảng tính Microsoft Excel. Điều này cho phép lập trình viên chỉ mất khoảng 5 giây để nạp trực tiếp bộ kiểm thử vào quy trình phát triển mà không cần chỉnh sửa thủ công bất kỳ dòng mã nào.

Kết luận

  • Luận văn xây dựng thành công giải pháp phân tích mã nguồn và sinh dữ liệu kiểm thử tự động toàn diện cho các dự án phần mềm C/C++.
  • Thuật toán LDFS kết hợp mô hình bộ nhớ trừu tượng giúp giải quyết triệt để bài toán sinh dữ liệu đầu tiên và loại bỏ hoàn toàn các ca kiểm thử dư thừa.
  • Công cụ thực nghiệm đạt độ phủ nhánh và câu lệnh tuyệt đối 100% trên 21 bài kiểm thử benchmark, tối ưu hóa vượt trội so với KLEE, CAUT, CREST và PathCrawler.
  • Giải pháp biên dịch một lần giúp giảm thiểu thời gian thực thi kiểm thử xuống hơn 70%, đồng thời hỗ trợ xuất mã nguồn kiểm thử chuẩn Google Test tự động.
  • Đóng góp khoa học của đề tài được khẳng định qua 2 công bố tại hội nghị NICS 2016 và SoICT 2017, mở ra lộ trình 12 tháng tiếp theo để tích hợp công cụ vào các hệ thống kiểm thử tự động công nghiệp quy mô lớn. Hãy áp dụng ngay giải pháp kiểm thử mã nguồn tự động này để nâng cao chất lượng phần mềm và tối ưu hóa ngân sách dự án của bạn!