鄭小萌,高 猛,滕俊元
軟件單元測試是軟件開發(fā)過程中重要的質(zhì)量保證活動,單元測試的質(zhì)量將很大程度上影響軟件產(chǎn)品的最終質(zhì)量.
目前隨著航天器復(fù)雜程度和指標(biāo)要求的不斷提高,航天器軟件的質(zhì)量也受到越來越廣泛的重視.尤其對于航天型號來說,軟件的可靠性、安全性設(shè)計尤為重要,正確的單元測試方法和有效的單元測試工具成為保證單元測試質(zhì)量與效率的關(guān)鍵因素.但由于航天器控制軟件是非常復(fù)雜的實時嵌入式軟件,存在工作模式多,與硬件結(jié)合密切,單元測試工作量大、測試難度高等特點,仍需研究有效的測試方法,設(shè)計高質(zhì)量的測試用例,來提高單元測試階段發(fā)現(xiàn)錯誤的能力[1-2].
本文通過分析總結(jié)航天器軟件單元測試的常見典型問題,結(jié)合航天器軟件單元測試的具體實踐,提出了一種“白-黑-白”盒混合的單元測試方法,該方法有效解決了現(xiàn)存的單元測試實施難題,同時提高了單元測試的質(zhì)量與效率,保證了航天器軟件的可靠性.
單元測試的目的在于發(fā)現(xiàn)程序單元模塊內(nèi)可能存在的各種錯誤.單元測試的內(nèi)容主要是對模塊的5個基本特性進(jìn)行評價,圖1對單元測試進(jìn)行了概要描述.
圖1 單元測試示意圖Fig.1 Diagram of unit test
模塊接口:在其他測試開始之前,首先要對通過模塊接口的數(shù)據(jù)進(jìn)行測試.若數(shù)據(jù)不能正確地輸入/輸出,則其他測試都是沒有意義的[3-4].
局部數(shù)據(jù)結(jié)構(gòu):檢查局部數(shù)據(jù)結(jié)構(gòu)以確保臨時存儲的數(shù)據(jù)在程序執(zhí)行過程中完整、正確.
重要的執(zhí)行路徑:執(zhí)行控制結(jié)構(gòu)中的所有獨立路徑(基本路徑)以確保模塊中的所有語句至少執(zhí)行一次.此時設(shè)計測試用例是為了發(fā)現(xiàn)因錯誤計算、不正確的比較或不適當(dāng)?shù)目刂屏鞫鸬腻e誤.此時,基本路徑測試和循環(huán)測試是最常用、最有效的測試技術(shù).
錯誤處理:一個好的設(shè)計應(yīng)能預(yù)見各種出錯條件,并預(yù)設(shè)各種出錯處理通路.
邊界測試:邊界測試是單元測試的最后一步,也是最重要的一項任務(wù).眾所周知軟件通常容易在邊界上失效,因而采用邊界值分析技術(shù),針對邊界值及其左、右值設(shè)計測試用例,很有可能發(fā)現(xiàn)新的錯誤[5].
綜上所述,單元測試期間常發(fā)現(xiàn)的錯誤可能出現(xiàn)在以上各個方面,收集分析、歸納總結(jié)相關(guān)問題數(shù)據(jù)對單元測試過程可起到有針對性的指導(dǎo)作用,也可為軟件質(zhì)量問題的舉一反三提供參考和依據(jù).
通過對航天型號軟件單元測試問題進(jìn)行梳理與分析,總結(jié)出以下單元測試典型多發(fā)問題類型,同時結(jié)合軟件實例給出了相關(guān)糾正措施,用于指導(dǎo)后續(xù)單元測試方法的選擇以及測試用例的設(shè)計,如表1所示.
表1 單元測試常見典型問題及實例Tab.1 Common typical problems and instance in unit test
通過分析典型多發(fā)問題的本質(zhì)及原因,可以得出結(jié)論,研究高效的單元測試方法、設(shè)計完整且充分的測試用例對于有效規(guī)避和解決軟件單元測試問題可以起到顯著作用,同時結(jié)合高可信度測試工具,不但能夠降低型號軟件的研制成本和周期,還可以提高測試效率[6-7],本文將著重介紹一種混合單元測試方法以及該方法中使用的自動化測試工具,并舉例說明了混合測試方法對于常見典型問題邏輯分支不可達(dá)、缺少邊界最大最小值覆蓋等情況的解決.
目前在航天領(lǐng)域,航天器軟件測試的標(biāo)準(zhǔn)規(guī)范主要參考有GJB/Z 141-2004軍用軟件測試指南、QJA300-2016航天軟件測試規(guī)范、QJ 3027-98航天型號軟件測試規(guī)范等文件.針對航天軟件單元測試的過程,要求根據(jù)任務(wù)書、項目開發(fā)計劃、軟件設(shè)計文檔等具體內(nèi)容,選擇適當(dāng)?shù)臏y試方法對軟件單元的功能、性能(精度、時間、容量等)、錯誤處理、邊界條件、內(nèi)存使用情況等方面進(jìn)行測試,驗證軟件單元是否正確地實現(xiàn)設(shè)計文檔中的功能、性能和其它設(shè)計約束等要求,并發(fā)現(xiàn)軟件單元的各種缺陷.
航天軟件單元測試一般應(yīng)符合以下技術(shù)要求:
(1) 對軟件設(shè)計文檔規(guī)定的軟件單元的功能、性能、接口等應(yīng)逐項進(jìn)行測試;
(2) 每個軟件特性應(yīng)至少被一個正常測試用例和一個被認(rèn)可的異常測試用例覆蓋;
(3) 測試用例的輸入應(yīng)至少包括有效等價類值、無效等價類值和邊界數(shù)據(jù)值;
(4) 在對軟件單元進(jìn)行動態(tài)測試之前,一般應(yīng)對軟件單元的源代碼進(jìn)行靜態(tài)測試;
(5) 語句覆蓋率達(dá)到100%;
(6) 分支覆蓋率達(dá)到100%;
(7) 修正判定/條件覆蓋率達(dá)到100%;
(8) 對輸出數(shù)據(jù)及其格式進(jìn)行測試.
目前單元測試一般采用白盒測試方法或者黑盒測試方法[8].黑盒測試用例設(shè)計是根據(jù)程序的功能進(jìn)行的,常用方法有等價類劃分、邊界值分析、判定表、因果圖等[9].此時在程序接口處進(jìn)行測試,檢查程序在接收輸入后是否能產(chǎn)生符合要求的輸出.然而程序的功能定義存在一些人為和主觀的因素,常常是不全面的;各個輸入數(shù)據(jù)和操作次序之間也有很多種組合關(guān)系,有些組合可能會產(chǎn)生問題,無法保證這些組合都經(jīng)過了測試.很顯然,普通的黑盒測試存在著局限性,很難衡量黑盒測試的完整性.因此引入白盒測試中的邏輯覆蓋指標(biāo)來標(biāo)識測試結(jié)果.
白盒測試針對程序的邏輯結(jié)構(gòu)設(shè)計測試用例,用邏輯覆蓋率來衡量測試的完整性.邏輯覆蓋測試方法包括:語句覆蓋、判定覆蓋、條件覆蓋、判定/條件覆蓋、組合覆蓋、路徑覆蓋.這幾種覆蓋對測試覆蓋的強(qiáng)度依次增強(qiáng).然而白盒測試依賴于程序的控制結(jié)構(gòu),若其本身有誤則無法發(fā)現(xiàn)錯誤.大部分結(jié)構(gòu)化測試策略沒有提供一個在路徑域中選擇測試數(shù)據(jù)的原則[10-11].
與此同時,國內(nèi)外有不少研究涉及單元測試領(lǐng)域,提出了大量的測試方法和測試?yán)碚?Paul C.Jorgensen在《Software Testing A Craftsman’s Approach》中就提出了軟件功能性測試和結(jié)構(gòu)性測試的方法;文獻(xiàn)[12]中提出了軟件單元測試通常覆蓋的區(qū)域,執(zhí)行單元測試應(yīng)該遵循的基本方法等.這些研究對軟件單元測試工作提供了大量的理論參考依據(jù),但研究往往立足于理論本身,缺乏工程操作中切實可行的解決方案.另外,從軟件組織對單元測試的實施現(xiàn)狀來看,許多軟件開發(fā)組織存在以下問題:
(1) 存在工作量大、測試人員設(shè)計測試用例數(shù)量多、測試周期長等問題,導(dǎo)致在軟件開發(fā)各個周期進(jìn)行高效的單元測試仍存在難度,急需提供有效的自動化測試手段;
(2) 現(xiàn)存的大多數(shù)自動化測試工具,由于針對用例設(shè)計相關(guān)功能效率較低,導(dǎo)致整體單元測試效率不高.
針對這些問題,本文介紹的“白-黑-白”盒混合單元測試方法中將使用一種自動化測試工具SunwiseAUnit,其基于代碼生成測試用例的特性可以很好地適用于航天軟件的回歸測試階段.利用工具自身簡單易用、高自動化的特點,使得測試人員可在大規(guī)模的回歸測試中進(jìn)行快速有效的自動化單元測試,同時自動生成的用例也可供測試人員快速校驗、復(fù)查已有手動設(shè)計的測試用例, 大幅度提高單元測試的效率.
如上節(jié)所述,白盒與黑盒測試方法具有各自的優(yōu)缺點,為充分利用兩種測試技術(shù)的優(yōu)勢,目前已形成一種介于黑盒和白盒之間的灰盒測試方法,考慮到在安全關(guān)鍵軟件測試中,單元測試的覆蓋準(zhǔn)則往往是雙百(語句、分支)甚至是三百(語句、分支、修正判定/條件覆蓋),本文在灰盒測試方法基礎(chǔ)之上提出了一種白-黑-白盒的混合單元測試方法(如圖2),該方法自動生成大量有效測試用例可以使得語句、分支、修正判定/條件覆蓋性(MC/DC)得到全面、有效的保障.
圖2 “白-黑-白”盒混合單元測試方法Fig.2 The white-black-white-box unit test method
步驟一:進(jìn)行白盒測試.在設(shè)計測試用例之前,首先關(guān)注模塊內(nèi)部的邏輯分支和路徑的執(zhí)行情況,即考慮以白盒測試中的邏輯覆蓋技術(shù)為基礎(chǔ),選擇出需要執(zhí)行的分支或路徑.該步驟利用自動單元測試工具SunwiseAUnit自動生成測試用例,主要優(yōu)勢體現(xiàn)如下:
(1) 基于工具提供的表格驅(qū)動可視化設(shè)計視圖,利用代碼分析技術(shù)自動獲取函數(shù)的接口、全局變量、底層調(diào)用等信息.用例編輯器提供用例輸入、預(yù)期輸出、運行結(jié)構(gòu)、樁函數(shù)等,提高了用例設(shè)計易用性.
(2) 基于最前沿的動態(tài)符號執(zhí)行技術(shù)與約束求解技術(shù),對位運算、浮點運算、全局變量、端口訪問、函數(shù)樁、函數(shù)指針等進(jìn)行特殊優(yōu)化并自動生成測試用例.測試用例自動生成功能的實現(xiàn)主要依靠單元測試用例生成引擎(核心如圖3所示),以前端處理器產(chǎn)生的中間表示為輸入,采用混合符號執(zhí)行技術(shù)、約束求解技術(shù)來產(chǎn)生滿足覆蓋準(zhǔn)則的測試輸入,經(jīng)過若干次迭代,最終生成測試輸入集.本部分除了包括C源碼級解釋器、符號執(zhí)行器、約束收集器、約束求解器等之外,重點提出了高效和高覆蓋率的路徑搜索及選擇策略.用例自動生成包含的3個主要部分:
圖3 用例生成引擎Fig.3 Test case automatic generation engine
1) 前端處理器(FrontEnd):給定源代碼和編譯配置,對被測軟件代碼進(jìn)行預(yù)處理、詞法/語法分析、CFG構(gòu)建和符號表構(gòu)建,產(chǎn)生后續(xù)分析所需要的各種中間表示IR.
2) 混合內(nèi)存模型(MemModel):混合內(nèi)存模型是解釋執(zhí)行和符號執(zhí)行的基礎(chǔ),提供對C語言各類語言結(jié)構(gòu)、類型、運算的內(nèi)存模型支持;具體地,又分為具體內(nèi)存模型和抽象內(nèi)存模型.
3) 單元測試用例生成引擎(Core):該部分是SunwiseAUnit的核心部分之一,本部分具體包括:
(a)C源碼級解釋器(CInt):對給定中間表示進(jìn)行具體解釋執(zhí)行,根據(jù)控制流圖對具體內(nèi)存模型進(jìn)行存取,并完成函數(shù)調(diào)用、條件跳轉(zhuǎn)等控制流的執(zhí)行;
(b)符號執(zhí)行器(SymEx):滿足真實嵌入式C程序,與源碼級解釋器同步執(zhí)行,在具體執(zhí)行過程中,維護(hù)抽象內(nèi)存模型的狀態(tài);
(c)約束收集器(ConsGen):在符號執(zhí)行引導(dǎo)下,收集一條路徑的約束公式;
(d)約束求解器(Solver):對收集的布爾約束進(jìn)行求解;
(e)高效和高覆蓋率的路徑搜索及選擇策略(PathSel):根據(jù)生成的輸入以及歷史數(shù)據(jù),采用高效的搜索算法,確定下一個要執(zhí)行的路徑,并指導(dǎo)解釋器迭代執(zhí)行.SunwiseAUnit工具采用當(dāng)前最新的理論成果,并根據(jù)大量真實案例進(jìn)行了算法調(diào)優(yōu).
(3) 利用工具自身提供的覆蓋率監(jiān)控技術(shù)(滿足DO-178B的覆蓋率測量功能),對代碼進(jìn)行插樁可以獲得語句、分支、MC/DC覆蓋率信息.
此外,很值得一提的是,工具自動靜默地生成測試執(zhí)行需要的腳本和測試驅(qū)動程序這項工作,大大減少了開展測試所需的額外工作量,可讓測試人員專注于用例設(shè)計,很好的解決了測試驅(qū)動難以編寫的難題.與此同時,工具無需依賴復(fù)雜編譯環(huán)境和設(shè)置,僅使用編譯好的被測軟件就可以進(jìn)行單元測試.該模式下測試用例數(shù)據(jù)自動轉(zhuǎn)換為目標(biāo)虛擬機(jī)的驅(qū)動腳本,通過這些腳本完成測試驅(qū)動、測試用例的輸入(包括樁)設(shè)置以及預(yù)期結(jié)果比較(過程如圖4所示),大大節(jié)省了測試過程中由于頻繁編譯浪費的時間成本.
圖4 無需編譯的測試用例執(zhí)行過程Fig.4 Execution of test cases without compile
步驟二:進(jìn)行基于邊界值分析法的黑盒測試.在上一步驟中已導(dǎo)出測試用例集合,保證了程序中的每一條語句和分支都至少執(zhí)行一次.本步驟從功能測試的角度,選擇邊界值分析法補(bǔ)充用例.經(jīng)驗表明輸入域的邊界比中間更加容易發(fā)生錯誤,為得到合理而嚴(yán)格的測試用例集,選擇該方法簡單而有效.按照邊界值分析的方法,應(yīng)該選取剛好等于、稍小于和稍大于等價類邊界的數(shù)據(jù)作為測試數(shù)據(jù).
步驟三:進(jìn)行白盒測試.除了步驟二中使用邊界值對用例進(jìn)行補(bǔ)充,還應(yīng)針對步驟一中最后獲取的覆蓋率信息所提示的沒有達(dá)到要求的情況,使用邏輯覆蓋進(jìn)行有針對性的測試用例設(shè)計.考慮邏輯覆蓋方法中由弱至強(qiáng)的遞進(jìn)關(guān)系,推薦使用路徑覆蓋法這種最強(qiáng)的邏輯覆蓋方法,達(dá)到最終覆蓋率100%的目的.
綜上所述,利用“白-黑-白”盒的測試方法能達(dá)到單元測試要求的完整性,又能避免不必要的重復(fù).同時利用自動化測試工具多項特點可以有效解決1.3節(jié)中提出的單元測試現(xiàn)存難題.這種測試方式比單一的黑盒或白盒方法更有效、更完整,從而使得整個單元測試過程達(dá)到既充分、高質(zhì)量,又最小花費的效果.
某軟件中待測函數(shù)為ptrToUserDefObserveTest1,其源碼如圖5所示.待測函數(shù)有兩個參數(shù)p和q,其中q為指向int的指針類型.該函數(shù)的功能是:若整型參數(shù)p在0~20之間時,指針q指向的值為p的2倍,上限值為30,否則指針q指向的值為-1.
圖5 待測函數(shù)源碼Fig.5 Function source code
基于“白-黑-白”混合測試方法實施步驟為:
1) 基于自動化單元測試工具,自動生成表2中的用例1與用例2,執(zhí)行用例獲得語句、分支及MC/DC覆蓋率信息.如圖6所示,語句覆蓋率4/7、分支覆蓋率1/4,即執(zhí)行了第一個True分支語句.
2) 基于邊界值分析法,補(bǔ)充設(shè)計測試用例3與用例5,選取剛好等于邊界值的數(shù)據(jù)進(jìn)行測試.
3) 基于邏輯覆蓋檢查,對未達(dá)到覆蓋率要求的語句或分支補(bǔ)充設(shè)計測試用例4.
表2 基于路徑覆蓋法的用例設(shè)計Tab.2 Test cases based on path coverage method
圖6 自動化工具函數(shù)運行結(jié)果Fig.6 Function running results of automation tool
對于更為復(fù)雜的程序,在步驟1中可同理創(chuàng)建剩余分支用例,復(fù)制用例給出輸入值與預(yù)期值即可,直至達(dá)到測試標(biāo)準(zhǔn),語句覆蓋率、分支覆蓋率、MC/DC覆蓋率均為100%(如圖7所示).
圖7 用例執(zhí)行結(jié)果三項覆蓋率達(dá)100%Fig.7 Test case coverage rate is 100%
目前在軟件測試技術(shù)研究領(lǐng)域,單元測試相關(guān)工作已經(jīng)得到了足夠重視,但實踐中常常由于開發(fā)周期、項目進(jìn)度、經(jīng)費等原因,導(dǎo)致單元測試不充分.因此在實際工作中深入研究和應(yīng)用有效的軟件單元測試方法,對于保證和提高航天器軟件的可靠性與安全性具有重要的現(xiàn)實意義.本文主要針對航天器軟件的單元測試方法進(jìn)行了一些探索,在實踐中總結(jié)出的“白-黑-白”盒的混合單元測試方法及測試用例自動生成技術(shù),可有效提高單元測試效率,同時對提高單元測試的質(zhì)量也具有現(xiàn)實指導(dǎo)作用.