姜 文,劉立康
(西安電子科技大學 通信工程學院,陜西 西安 710071)
軟件測試[1-2]是保證軟件質量和可靠性的重要手段。其中覆蓋率測試就是監控軟件代碼覆蓋率的一種有效的測試方法,通過一系列的測試集來找出哪些代碼沒有被執行到,統計程序各類語句執行的覆蓋率,并對代碼的執行路徑覆蓋范圍進行評估、分析。
隨著軟件開發技術的不斷發展,軟件持續集成[3-5]技術已經成為大型軟件開發過程中重要的組成部分。通過持續集成工具構建覆蓋率工程可以方便地進行軟件代碼的覆蓋率測試,及時提供軟件開發過程中的覆蓋率數據,從而有效監控和改進軟件源代碼的質量,改進和提升軟件開發和測試工作。
覆蓋率測試[6-10]是一種白盒測試方法。覆蓋率度量指標有多種,包括語句覆蓋、分支覆蓋、函數覆蓋、條件覆蓋、分支/條件覆蓋、路徑覆蓋等。其中語句覆蓋是最基本的覆蓋標準。覆蓋率測試以程序內部的邏輯結構為基礎,設計若干測試用例,在這些測試用例運行時,提取相關的覆蓋率信息。
插樁技術[11-14]是在源程序的某些位置插入語句或程序段,但并不破壞程序的完整性的一種技術。在插樁過程中,插樁的位置根據程序的結構,測試的要求以及實現的測試目的進行設定。軟件插樁技術能夠根據實際需要,獲取軟件的各種信息。代碼插樁是實現覆蓋率測試的關鍵技術之一,如今大多數的覆蓋率測試工具均采用代碼插樁技術。
代碼覆蓋率測試主要應用在兩個方面:
(1)評估測試質量:根據軟件的代碼覆蓋率檢查報告,發現漏測場景,開發工程師分析之后給出改進建議,測試工程師補充新的測試點和新的測試用例;
(2)幫助識別冗余代碼:開發工程師對代碼覆蓋率檢查報告進行分析之后,發現冗余代碼,對程序代碼進行優化與重構。
在Linux上的C/C++軟件開發一般使用gcc/g++作為編譯器。gcov工具[15-16]是伴隨著gcc發布的,是gcc附帶的一個代碼覆蓋率分析工具,配合gcc共同實現對單個或多個C/C++文件進行語句和分支覆蓋率測試。
gcc編譯應用程序時加選項-fprofile -arcs和-ftest-coverage。這樣,在編譯過程中,gcc對每個c/cpp文件生成一個*.gcno數據文件,并且同時對應用程序進行插樁。運行插樁后的程序時,每個c/cpp程序的動態信息會保存在*.gcda數據文件中。
*.gcno文件包含了基本塊圖和相應塊的源碼的行號信息。包含基本塊的信息,代碼行和塊的映射關系。
*.gcda文件包含了程序分支跳變的次數和其他概要信息(gcda只能在程序運行完畢后產生)。包含代碼行執行的情況以及覆蓋率的信息歸納。
gcov工具利用編譯時生成的.gcno數據文件以及運行時生成的.gcda數據文件,得到程序的代碼覆蓋信息,并且以注釋源代碼的形式顯示執行過和未執行過的代碼。
gcc和gcov進行應用程序覆蓋率測試的流程如圖1所示。

圖1 gcov覆蓋率測試流程
覆蓋率數據產生的過程如下:
(1)插樁編譯程序源代碼;生成可執行文件和源代碼文件相應的*.gcno文件。
(2)運行測試程序,生成源代碼文件相應的*.gcda文件。
(3)使用gcov獲取文本形式的覆蓋率數據文本文件*.gcov;也可以使用lcov工具獲取html形式的覆蓋率數據。
gcov工具計算速度快,可以準確計算覆蓋率。被測程序的編譯插樁是由gcc完成,gcov負責數據的分析和顯示。但是gcov工具只能支持語句以及分支兩種覆蓋率測試功能,不適用于大型軟件和復雜開發環境的覆蓋率測試,不能給出軟件開發過程中新增代碼的覆蓋率測試。
軟件代碼覆蓋率測試通過持續集成工具,完成對軟件各模塊的插樁編譯、版本包出包。在版本包測試過程中完成代碼覆蓋率數據采集,對相關數據進行加工處理后生成覆蓋率報告。
覆蓋率數據分為三種類型:
(1)當前軟件代碼的覆蓋率。
通過覆蓋率測試獲得當前軟件代碼的覆蓋率數據和各模塊的覆蓋率數據。這個數據反映了軟件開發過程中程序代碼總體的代碼覆蓋率狀況。
(2)新增代碼的覆蓋率。
通過基線版本代碼和當前版本軟件代碼的比較分析,得到新增與修改的代碼的列表文件,結合測試過程中得到的覆蓋率數據,獲得新增代碼的覆蓋率。這個數據反映了軟件開發過程中新增程序代碼或修改了的程序代碼覆蓋率狀況。
(3)生成VBS(validation before submission)數據庫。
VBS數據庫由測試用例覆蓋軟件模塊代碼行的數據組成,反映了軟件模塊代碼行和測試用例的對應關系。
基于持續集成的覆蓋率測試流程如圖2所示。

圖2 基于持續集成的覆蓋率測試流程
(1)下載代碼:從版本庫下載基線版本代碼和更新當前代碼版本包。
(2)插樁編譯鏈接:對當前版本代碼進行插樁編譯,生成插樁編譯進程文件和插樁信息文件包,出插樁版本包。
(3)軟件代碼預處理:對基線版本代碼、更新后的當前代碼和插樁信息文件包進行預處理,生成插樁數據庫Frame.bin(里面包含了插樁文件、函數、有效行信息)和相關文件。
(4)HLT(HIGH LEVEL TEST)測試:在測試環境中對插樁版本包進行HLT測試,測試過程中收集相關數據,每個軟件模塊生成覆蓋率數據文件為*.hcovd;每個測試用例生成用例ID命名的*.bin覆蓋率數據文件。
(5)處理覆蓋率數據文件:將插樁信息文件包、覆蓋率數據文件*.hcovd和用例的覆蓋率文件*.bin提交覆蓋率數據處理中心,軟件模塊的覆蓋率數據文件*.hcovd匯總處理生成Case.bin數據庫;用例的覆蓋率文件*.bin匯總處理生成VBS數據庫。
(6)生成覆蓋率報告:將插樁數據庫Frame.bin和相關文件提交覆蓋率數據中心;將覆蓋率數據庫Case.bin提交覆蓋率數據中心。覆蓋率數據中心依據提交的相關數據生成可以閱讀的覆蓋率報告。
工程采用軟件配置管理工具SVN和持續集成工具ICP-CI開展持續集成工作。軟件產品開發階段每天都要把源代碼合入版本庫中,通過持續集成(CI)系統進行集成構建。通常每周進行一次覆蓋率檢查。覆蓋率檢查工程子系統關系圖如圖3所示。

圖3 覆蓋率檢查工程子系統關系圖
大型軟件系統通常采用分布式CI系統。CI系統由主控服務器(CI Master)和代理服務器(CI Agent)組成,代碼中心和CovReport均為特殊的代理服務器,如圖3虛線方框所示。
4.1.1 搭建覆蓋率檢查工程
在主控服務器的ICP-CI工具頁面上搭建覆蓋率檢查工程,工程命名為:“產品名_版本號_COV”,通過代理服務器標簽將各種任務下發代理服務器執行。
4.1.2 代碼更新和下載基線版本代碼
代碼中心登陸SVN版本庫,完成當前代碼更新和下載基線版本代碼。
(1)當前代碼更新。
編寫代碼更新的批處理腳本,并把代碼更新的腳本配置在任務中,執行代碼更新任務。對于配置管理工具SVN,調用SVN的“update”命令更新代碼中心的軟件代碼。
(2)下載基線版本包代碼。
通常每周進行一次全量集成構建,生成轉測試版本包,提交測試組進行全面測試,測試通過后產生測試(Tested)基線。覆蓋率檢查工程需要從版本庫下載某個特定的測試基線版本代碼,下載的版本代碼的文件壓縮包為BaseCode.zip。
4.1.3 插樁編譯
CI系統的代理服務器從代碼中心下載更新后的當前代碼壓縮包CurrentCode.zip,采用功能更為強大的插樁工具Avatar進行軟件代碼的插樁編譯。
(1)makefile文件的修改。
使用Avatar進行插樁編譯時,需要鏈接Avatar的靜態庫:
-L /opt/Linux_avatar_64-INCSCore_suse_10_x86-64;
插樁編譯腳本增加插樁工具的初始化部分,清理之前插樁工程遺留的文件和目錄,腳本內容如下:
if [-e /opt/linux_avatar_64/HLLT_init.sh]; then
source /opt/linux_avatar_64/ HLLT_init.sh
rm-rf /opt/linux_avatar_64/llt
(2)插樁編譯成功的判斷標準。
完成插樁編譯之后,如果模塊的進程文件與插樁信息文件包都生成了,則表示插樁編譯成功;如果僅有插樁信息文件包生成,則表示插樁編譯沒有成功,插樁信息文件包中的插樁信息文件名必定是亂碼。
4.1.4 生成插樁版本包
插樁編譯任務完成后,在ICP-CI工具的任務頁面配置出包任務package,將出包腳本配置到任務中。運行出包腳本,生成包含各模塊的進程文件和插樁信息文件包的插樁版本包。代理服務器將插樁版本包提交到代碼中心。
在標簽為CovReport的CI代理服務器上進行插樁數據預處理,從代碼中心下載基線代碼版本BaseCode.zip、當前代碼版本包CurrentCode.zip和插樁信息文件包。覆蓋率工程需要基線版本代碼作為統計新增代碼覆蓋率的參考基準。
插樁數據預處理過程如下:
(1)解壓BaseCode.zip、CurrentCode.zip和插樁信息文件包,采用專用的統計分析工具處理相關文件。
(2)生成插樁數據庫Frame.bin,Frame.bin文件合并了所有插樁編譯生成的數據文件,給出插樁文件函數的代碼行信息。數據記錄了文件名、文件路徑、函數名、函數起始行號、函數終止行號等信息。
(3)當前代碼版本包中的非新增與修改的代碼文件的信息寫入相關文件;所有插樁編譯模塊的源文件名稱與源文件路徑寫入相關文件。
代碼中心將插樁版本包提交到測試任務集成控制中心(test integration control center,TICC),TICC自動完成測試用例管理、測試環境配置、測試版本安裝與卸載、自動化測試用例執行等任務。
HLT測試檢查過程如下所示:
(1)在自動化工廠環境中卸載前一次的插樁版本包,安裝新的插樁版本包,下發自動化測試用例連跑任務,并打開測試套。
(2)測試套在用例執行開始前清除前一次的覆蓋率數據,用例執行結束之后,從執行環境上收集用例對應的覆蓋率數據。將每個用例的覆蓋數據整理,合并成一個用例ID命名的*.bin文件。
(3)執行測試結果回收整理,完成HLT測試檢查后,會生成模塊的覆蓋率數據文件*.hcovd。覆蓋率數據文件的文件名稱通常由以下格式組成:
模塊名_模塊鏈接的時間_插樁編譯時間戳_代碼覆蓋率數據文件生成的時間_生成覆蓋率文件的測試執行機IP地址.hcovd
將軟件模塊的覆蓋率數據文件*.hcovd和用例的覆蓋率數據文件*.bin提交到覆蓋數據處理服務器(標簽為CaseBinBuider),代碼中心將插樁信息文件包也提交到覆蓋率數據處理服務器。對覆蓋率數據文件*.hcovd進行加工處理,生成覆蓋率數據庫Case.bin。對用例的覆蓋率數據文件*.bin加工處理,生成VBS數據庫。
代碼覆蓋率數據中心(標簽為CovCenter)進行覆蓋率數據統計工作。將插樁數據庫Frame.bin、覆蓋率數據流Case.bin和其他相關的數據文件提交到CovCenter,開展如下工作:
(1)代碼覆蓋中心將各種覆蓋率信息寫入MYSQL數據庫。
(2)生成可以閱讀的覆蓋率報告,覆蓋率結果文件為Cover.xml。代碼覆蓋率報告提供了宏觀的軟件代碼覆蓋率信息。將這些數據提交公司質量部門,作為軟件開發過程的度量指標之一,監測軟件開發過程。
VBS數據庫提供了微觀的覆蓋率信息,提供代碼軌跡與測試用例的對應關系。
在HLT檢查過程中,執行測試結果回收整理的環境將每個用例的覆蓋數據進行整理,合并成一個用例ID命名的*.bin文件。將這些文件匯總處理生成VBS數據庫,數據庫內容如表1所示。

表1 VBS數據庫內容
數據庫字段主要由TestCase(用例名稱)、CodeLine(執行用例覆蓋的代碼行)和Codefile(代碼所在的文件名)組成。
(1)程序代碼、測試用例、功能特性之間的對應關系。
在修改程序代碼時,通過VBS數據庫篩選可以查到代碼行相關聯的測試用例;通過TMSS數據庫可以查到測試用例相關聯的軟件功能特性,如圖4所示。

圖4 代碼、測試用例、功能特性關聯圖
TMSS(test management service system)測試信息管理中心,負責測試用例、自動化測試腳本以及測試任務相關信息的管理。TMSS中的測試用例信息庫提供測試用例與軟件功能特性之間的對應關系。
(2)幫助了解開發單元的功能特性。
長期的增量開發,功能越來越多,特性交互場景也越來越多,即使編一行代碼也要花費很多時間去分析]和梳理交互場景,對開發人員經驗的要求逐漸提高。提交文件名和代碼行號,查看影響本行代碼的測試用例,查看本行代碼涉及的功能特性、場景,可以幫助理解代碼。
(3)方便問題單修改。
修改完問題單后,通過篩選給出影響代碼的用例集進行回歸測試,快速驗證修改代碼的兼容性。
(4)提高開發質量和效率。
將VBS篩選功能集成到研發桌面上,開發人員一鍵便可完成代碼的影響分析,從而提高程序代碼開發的效率和質量。
(5)提升測試用例。
測試人員通過對用例對應的代碼和軟件功能特性的對比分析,可以發現測試用例存在的一些問題,從而修改優化測試用例或者增加新的測試用例。
某公司的一個軟、硬件結合的大型開發項目,總的代碼量超過兩百萬行。軟件產品采用C/C++進行軟件開發。采用的配置管理工具為SVN;持續集成工具為ICP-CI。CI系統由1臺主控服務器、14臺代理服務器組成,1臺用作代碼中心,2臺用于插樁數據預處理。每周進行一次覆蓋率檢查。表2給出其中一次檢查的覆蓋率數據。
在軟件開發過程中,覆蓋率測試主要關注新增代碼的覆蓋率情況,選擇測試用例注重新增代碼的測試,要求新增代碼覆蓋率大于65%,對于整體的代碼覆蓋率,各軟件產品根據產品自身情況靈活分析和處理。
(1)表2中軟件產品版本包新增代碼覆蓋率數據大于65%,滿足度量指標要求。
(2)表2中模塊MK1、MK2、MK4和MK5新增代碼覆蓋率數據大于65%,滿足度量指標要求。
(3)表2中模塊MK3和MK4新增代碼覆蓋率數據低于65%,需要根據模塊的測試報告分析該模塊未被測試用例覆蓋到的場景,需要對未覆蓋到的場景增加自動化測試用例。

表2 軟件產品版本包與版本中模塊的代碼覆蓋率
工作實踐表明,基于持續集成的代碼覆蓋率檢查在軟件開發過程可以發揮重要作用,有助于及時發現開發和測試過程存在的各種問題。根據代碼覆蓋率的檢查報告分析測試場景,及時補充測試用例和優化代碼。代碼覆蓋率作為軟件度量指標,給軟件開發過程管理提供了一項重要的評價指標。軟件開發過程中做好代碼覆蓋率檢查工作,有助于提高軟件產品的質量,降低軟件開發的成本。
[1] MYERS G J,BADGETT T,SANDLER C.Art of software tes-
ting[M].3rd ed.Hoboken,New Jersey,U.S:John Wiley& Sons,2012.
[2] 趙 翀,孫 寧.軟件測試技術:基于案例的測試[M].北京:機械工業出版社,2013.
[3] 姜 文,劉立康.基于SVN的應用軟件持續集成[J].計算機測量與控制,2016,24(3):109-113.
[4] DUVALL P M,MATYAS S,GLOVE A.持續集成軟件質量改進和風險降低之道[M].北京:電子工業出版社,2012.
[5] 姜 文,劉立康.軟件配置管理中的基線問題研究[J].計算機技術與發展,2016,26(6):6-10.
[6] 于全喜.嵌入式軟件路徑覆蓋測試數據采集研究與實現[D].西安:西安理工大學,2009.
[7] DELAMARO M E,VINCENZI A M R,MALDONADO J C.A strategy to perform coverage testing of mobile applications[C]//Proceedings of the 2006 international workshop on automation of software test.New York,NY,USA:ACM,2006:118-124.
[8] WOODWARD M R,HENNELL M A.On the relationship between two control-flow coverage criteria all JJ-paths MCDC[J].Information and Software Technology,2006,48(7):433-440.
[9] MALEVRIS N,YATES D F.The collateral coverage of data flow criteria when branch testing[J].Information and Software Technology,2006,48(8):676-686.
[10] WU X,LI J J,WEISS D,et al.Coverage-based testing on embedded systems[C]//Proceedings of the 29th international conference on software engineering workshops.Minneapolis,Minnesota,US:IEEE,2007:204-209.
[11] 郭 銳,李 博,彭寶新.用于覆蓋測試的代碼插樁程序設計與實現[J].科學技術與工程,2013,13(30):9072-9077.
[12] 張 榮,王曙燕.基于插樁技術的動態測試研究與實現[J].現代電子技術,2011,34(4):50-52.
[13] 路 翠.嵌入式軟件白盒測試中插樁技術的研究與應用[D].北京:北京工業大學,2010.
[14] 王 偉.基于多Agent的嵌入式軟件測試系統研究與實現[D].南京:南京航空航天大學,2011.
[15] 王叔娥.嵌入式軟件動態分析技術的研究[D].成都:電子科技大學,2011.
[16] 朱 麗.嵌入式軟件動態測試平臺的研究與實現[D].福州:福建師范大學,2013.