文獻(xiàn)標(biāo)識(shí)碼: A
文章編號(hào): 0258-7998(2014)12-0125-04
0 引言
隨著信息化軍事技術(shù)的不斷深入,嵌入式實(shí)時(shí)軟件已在工業(yè)控制、電子信息以及武器裝備等系統(tǒng)中發(fā)揮著越來越重要的作用;同時(shí)隨著嵌入式軟件的規(guī)模和復(fù)雜性的不斷提高,作為有效保證和驗(yàn)證軟件質(zhì)量的重要環(huán)節(jié)和依據(jù),軟件測(cè)試已逐漸成為軟件研制成本最高的階段[1]。如何采用有效的嵌入式軟件工程化測(cè)試方法提高嵌入式軟件的質(zhì)量和可靠性以及增強(qiáng)軟件組織自身的軟件測(cè)試能力具有極其重要的意義。
錯(cuò)誤越早發(fā)現(xiàn),項(xiàng)目付出的代價(jià)就越少,單元測(cè)試作為軟件項(xiàng)目中最早介入的測(cè)試活動(dòng)[2],易于發(fā)現(xiàn)程序的錯(cuò)誤和缺陷,也易于實(shí)現(xiàn)代碼測(cè)試的完全覆蓋,因此單元測(cè)試的好壞對(duì)于軟件質(zhì)量的保證起著非常關(guān)鍵的作用。然而由于嵌入式軟件的特殊性,如實(shí)時(shí)性強(qiáng)、與硬件緊密相關(guān)、訪問硬件麻煩,在開發(fā)環(huán)境下模擬整個(gè)系統(tǒng)存在困難性,這使得測(cè)試一直是個(gè)難點(diǎn),特別是單元測(cè)試,由于項(xiàng)目周期不允許,一些嵌入式軟件沒有進(jìn)行單元測(cè)試或單元測(cè)試不徹底;有些嵌入式軟件代碼具有較高的耦合性,使單元測(cè)試難以進(jìn)行;測(cè)試人員對(duì)于嵌入式軟件單元測(cè)試過于依賴自動(dòng)化測(cè)試工具,使測(cè)試效果不能令人滿意,測(cè)試不規(guī)范,效率低[3],且無法確保嵌入式軟件單元測(cè)試的充分性和有效性。
針對(duì)上述問題,本文以集控嵌入式軟件為例,重點(diǎn)研究了基于Testbed軟件測(cè)試工具的靜態(tài)分析和動(dòng)態(tài)測(cè)試方法,提出了一種較為完整和可操作的單元測(cè)試解決方法。研究分析了靜態(tài)分析輸出的度量模型值對(duì)嵌入式軟件的影響,并根據(jù)度量值提出了提高軟件代碼質(zhì)量的措施;介紹了基于Tornado編譯環(huán)境的動(dòng)態(tài)測(cè)試過程,并基于圈復(fù)雜度[4]提出了一種優(yōu)先級(jí)的動(dòng)態(tài)分析測(cè)試策略,以確保單元測(cè)試的充分性和有效性,提高軟件測(cè)試方法的效率和規(guī)范性,確保軟件的質(zhì)量。
1 被測(cè)系統(tǒng)概述
被測(cè)系統(tǒng)集控軟件是一個(gè)實(shí)時(shí)嵌入式系統(tǒng),運(yùn)行在集控模塊控制單元內(nèi),控制單元由底板、CPU板和AD/DA板組成。板卡之間采用CPCI總線,通過CPU板上的兩路LAN接口與通信集控柜連接,完成與操舵臺(tái)、數(shù)采站、交流主配電柜、遙控操縱臺(tái)、綜控柜和顯控臺(tái)的網(wǎng)絡(luò)信息交換。CPU板上的一路RS422A接口與通信集控柜中的導(dǎo)航定位分機(jī)連接,完成導(dǎo)航定位信息的讀?。涣硪宦稲S422A接口與集控臺(tái)內(nèi)手控模塊連接,完成指令的轉(zhuǎn)發(fā)和手控狀態(tài)的傳輸。控制單元中的AD/DA板與左/右主機(jī)齒輪箱執(zhí)行器連接,完成速度調(diào)整。軟件的總體結(jié)構(gòu)圖如圖1所示。
集控軟件使用C++/C語(yǔ)言編寫,程序基于模塊化思想設(shè)計(jì),在實(shí)時(shí)多任務(wù)操作系統(tǒng)VxWorks上實(shí)現(xiàn),基于Tornado的開發(fā)環(huán)境。按功能劃分模塊,采用多任務(wù)下的同步機(jī)制,通過消息實(shí)現(xiàn)各個(gè)模塊之間的通信。
在該軟件的單元測(cè)試中,采用靜態(tài)分析和動(dòng)態(tài)測(cè)試相結(jié)合的方法來評(píng)估和完成軟件的充分性和測(cè)試的完備程度。
2 集控軟件測(cè)試關(guān)鍵步驟及實(shí)現(xiàn)
2.1 基于Tornado的仿真單元測(cè)試環(huán)境搭建
集控軟件單元測(cè)試工具采用的是Testbed,它是英國(guó)LDRA公司開發(fā)的一種軟件代碼測(cè)試及分析工具,主要用在軟件測(cè)試和軟件維護(hù)階段以便提高軟件產(chǎn)品的質(zhì)量,該工具可提供編碼規(guī)則檢查、軟件度量分析、數(shù)據(jù)流分析、覆蓋率分析等功能[5]。在Testbed /Tbrun工具下配置集控嵌入式軟件的仿真單元測(cè)試環(huán)境,需滿足在Tornado2.2集成開發(fā)環(huán)境下成功編譯、執(zhí)行測(cè)試驅(qū)動(dòng)程序,具體步驟如下:
(1)借助Tbconfig工具完成Tornado2.2編譯環(huán)境的配置,并指定該開發(fā)環(huán)境的和測(cè)試工具的路徑;
(2)配置生成被測(cè)函數(shù)的驅(qū)動(dòng)模板C:\LDRA_Toolsuite\
Vxworks 路徑下的vxworks_Cshlayout_663.dat,該模板用于生成被測(cè)函數(shù)的測(cè)試驅(qū)動(dòng);
(3)配置函數(shù)的插樁模板C:\Testbed760\Vxworks\Vxworks_
cinstr.dat,插樁模板的作用是對(duì)被測(cè)函數(shù)的入口、出口、控制流進(jìn)行插樁,在單元測(cè)試結(jié)束時(shí),用于分析單元測(cè)試的覆蓋率,以確定測(cè)試用例是否滿足覆蓋率需求。
2.2 集控實(shí)時(shí)嵌入式軟件的靜態(tài)分析
靜態(tài)分析是通過工具在非運(yùn)行狀態(tài)下對(duì)程序結(jié)構(gòu)、數(shù)據(jù)結(jié)構(gòu)、代碼質(zhì)量的分析,提取代碼大量的靜態(tài)內(nèi)部信息,為代碼審查以及動(dòng)態(tài)測(cè)試提供輔助參考的信息[5]。下面以集控軟件的網(wǎng)絡(luò)通信模塊UdpSocket.cpp為例,對(duì)其靜態(tài)測(cè)試過程和結(jié)果進(jìn)行詳細(xì)說明。
2.2.1 靜態(tài)分析過程
運(yùn)行測(cè)試工具Testbed,打開UdpSocket.cpp源程序,選擇MISRA編碼規(guī)則,然后在Select Analysis窗口下選擇分析菜單對(duì)該文件進(jìn)行靜態(tài)分析,通過該項(xiàng)分析,為測(cè)試人員提供了該文件中各函數(shù)之間的調(diào)用關(guān)系模型,圖2幫助測(cè)試人員簡(jiǎn)單明了地以顏色區(qū)分來顯示模塊間的調(diào)用關(guān)系,紅色為自定義函數(shù),綠色為系統(tǒng)函數(shù)。圖3是UdpSocket.cpp中各子函數(shù)通過度量的比例分析數(shù),可得出總函數(shù)的度量為91%,清晰性為 93%,可維護(hù)性為91%,測(cè)試性為100%。圖4是UdpSocket.cpp基于MaCabe的軟件度量模型對(duì)程序分析的Kiviat圖,每一軸代表一類度量元,被測(cè)試源代碼以扇形的結(jié)構(gòu)顯示出來,綠色表示符合質(zhì)量標(biāo)準(zhǔn)。圖5是UdpSocket.cpp基本節(jié)點(diǎn)數(shù)和基本圈復(fù)雜度數(shù)據(jù)分析柱狀圖。通過這些圖可以幫助測(cè)試人員了解代碼的靜態(tài)內(nèi)部信息,發(fā)現(xiàn)缺陷。
2.2.2 靜態(tài)測(cè)試分析
靜態(tài)分析的結(jié)果能夠幫助測(cè)試人員從代碼內(nèi)部結(jié)構(gòu)信息中開展工作,幫助質(zhì)量管理人員從軟件質(zhì)量度量中進(jìn)行質(zhì)量監(jiān)督[5]。通過對(duì)軟件靜態(tài)分析的總結(jié),可以從降低代碼的圈復(fù)雜度和提高代碼的注釋率兩方面提高軟件代碼質(zhì)量。
?。?)降低代碼的圈復(fù)雜度
圈復(fù)雜度是應(yīng)用最廣泛的靜態(tài)度量之一,用來衡量一個(gè)函數(shù)判定結(jié)構(gòu)的復(fù)雜程度,圈復(fù)雜度公式V(G)=P+1,P是代碼中判定結(jié)點(diǎn)的數(shù)量[6]。程序的可能存在錯(cuò)誤數(shù)和圈復(fù)雜度有著很大的相關(guān)性,圈復(fù)雜度越大代表程序代碼的質(zhì)量低并且難以維護(hù)和測(cè)試[6]。
當(dāng)代碼中遇到判定條件比較復(fù)雜時(shí),可以將判定條件的表達(dá)式提前計(jì)算存儲(chǔ)在一個(gè)變量中,簡(jiǎn)化判斷條件,減低代碼的圈復(fù)雜度,減少bug數(shù)。例如UdpSocket.cpp文件中有判定語(yǔ)句:
If ((UNIT)(szTemp[0] == 0xA5 && (UNIT)(szTemp[1]
== 0xA5) && (UNIT)(szTemp[2] == 0xA3))
{
}
該判定條件的判定結(jié)點(diǎn)為3,圈復(fù)雜度即為4,將代碼優(yōu)化之后如下:
int num;
num=(UNIT)(szTemp[0] == 0xA5 && (UNIT)(szTemp[1] == 0xA5) && (UNIT)(szTemp[2] == 0xA3);
if (num)
{
}
優(yōu)化后的代碼判定結(jié)點(diǎn)為1,圈復(fù)雜度為2。
?。?)提高代碼的注釋率
提高代碼的注釋率可增加代碼的可讀性和可維護(hù)性,為每個(gè)代碼塊添加注釋,并在每一層使用統(tǒng)一的注釋方法和風(fēng)格,包括每個(gè)類和每個(gè)方法。
2.3 集控實(shí)時(shí)嵌入式軟件的動(dòng)態(tài)測(cè)試
2.3.1 測(cè)試用例設(shè)計(jì)
?。?)測(cè)試用例數(shù)據(jù)的合理設(shè)計(jì)
測(cè)試用例的設(shè)計(jì)是為了提高測(cè)試代碼的覆蓋率,動(dòng)態(tài)測(cè)試中最重要的過程是如何設(shè)計(jì)測(cè)試用例,著重測(cè)試數(shù)據(jù)的輸入設(shè)計(jì)。對(duì)于一般標(biāo)準(zhǔn)類型的輸入變量(如int、char、float、double等)并沒有多大問題,當(dāng)變量是數(shù)組、指針、結(jié)構(gòu)體、VxWorks中的FUNCPTR、LOCAL等特殊類型時(shí),數(shù)據(jù)輸入就需要特別注意。當(dāng)數(shù)組的下標(biāo)值很大時(shí),進(jìn)行手工輸入是不可能的,可以在TBrun環(huán)境中有選擇地對(duì)需要的變量進(jìn)行賦值或者在插樁后的代碼中插入數(shù)組的初始化語(yǔ)句對(duì)整個(gè)數(shù)組進(jìn)行賦值;當(dāng)變量是指針時(shí),由于不能給指針直接賦地址,輸入指針采用映射的方法將指針變量映射成相應(yīng)的自定義變量作為指針的輸入值;結(jié)構(gòu)體變量賦值不正確時(shí)很容易導(dǎo)致測(cè)試用例跑飛掉,需要從源代碼找到該變量創(chuàng)建的賦值函數(shù),將該函數(shù)作為變量的輸入值,必要時(shí)還需要添加函數(shù)的參數(shù),例如本文需測(cè)試的文件CUdpSocket.cpp中有消息隊(duì)列數(shù)據(jù)結(jié)構(gòu)體:
MSG_Q_ID msgId//接收消息的消息隊(duì)列ID號(hào)
其中MSG_Q_ID屬于VxWorks的系統(tǒng)調(diào)用,在文件中有對(duì)msgId的賦值語(yǔ)句:
msgId=msgQGreate()//創(chuàng)建消息隊(duì)列
在創(chuàng)建測(cè)試用例中對(duì)類型是MSG_Q_ID的變量輸入值應(yīng)設(shè)為msgQGreate()。
?。?)通過盡量少的測(cè)試用例達(dá)到盡量高的代碼覆蓋率。測(cè)試用例是以程序的內(nèi)部結(jié)構(gòu)為基礎(chǔ)來設(shè)計(jì)的,需要盡可能多地覆蓋程序的內(nèi)部邏輯結(jié)構(gòu)。
2.3.2 測(cè)試驅(qū)動(dòng)的工作原理
動(dòng)態(tài)測(cè)試過程中無法及時(shí)提供測(cè)試運(yùn)行所需的真正目標(biāo)機(jī)及其操作系統(tǒng),必須正確配置開啟仿真模擬器并將其作為虛擬目標(biāo)機(jī),將Testbed經(jīng)過編譯環(huán)境鏈接后生成的測(cè)試驅(qū)動(dòng)程序下載到仿真模擬器中運(yùn)行。每執(zhí)行一個(gè)測(cè)試用例需要重新編譯和執(zhí)行,函數(shù)的驅(qū)動(dòng)程序是由Testbed/Tbrun根據(jù)驅(qū)動(dòng)模板自動(dòng)生成的,驅(qū)動(dòng)程序是一個(gè)基于控制臺(tái)的程序,主要完成動(dòng)態(tài)測(cè)試環(huán)境初始化,當(dāng)調(diào)用測(cè)試用例時(shí)要執(zhí)行函數(shù)ldra_qq_execute_test_
case_1(),該函數(shù)負(fù)責(zé)被測(cè)函數(shù)入口參數(shù)的初始化,然后再調(diào)用被測(cè)函數(shù)完成整個(gè)測(cè)試的過程。
2.3.3 采用圈復(fù)雜度優(yōu)先級(jí)的動(dòng)態(tài)測(cè)試策略
有效的測(cè)試策略可使軟件測(cè)試的效率最大化,從而滿足測(cè)試的各項(xiàng)要求并降低測(cè)試成本。由于基于Tornado開發(fā)環(huán)境的集控軟件代碼規(guī)模較大,功能模塊較多,結(jié)構(gòu)復(fù)雜,因此為了提高測(cè)試效率,制定了一種基于優(yōu)先級(jí)的動(dòng)態(tài)測(cè)試策略,具體步驟如下:
?。?)通過Testbed測(cè)試工具對(duì)每個(gè)文件靜態(tài)分析的結(jié)果從基本節(jié)點(diǎn)數(shù)和基本圈復(fù)雜度數(shù)據(jù)來分析柱狀圖,得到每一個(gè)文件中被測(cè)函數(shù)的圈復(fù)雜度和節(jié)點(diǎn)數(shù)。
(2)按圈復(fù)雜度進(jìn)行高低排序,對(duì)圈復(fù)雜度高且重要的函數(shù)進(jìn)行重點(diǎn)測(cè)試。圖5可看出UdpSocket.cpp文件中SocketSndData()函數(shù)的圈復(fù)雜度最高,因此首先對(duì)該函數(shù)進(jìn)行重點(diǎn)測(cè)試。
?。?)編譯鏈接通過之后,執(zhí)行設(shè)計(jì)好的測(cè)試用例,用監(jiān)控到的控制流信息來分析程序的覆蓋率,依據(jù)分析結(jié)果不斷補(bǔ)充和優(yōu)化測(cè)試用例。根據(jù)各模塊的語(yǔ)句和分支覆蓋率、已執(zhí)行語(yǔ)句、執(zhí)行路徑以及未執(zhí)行的語(yǔ)句,判定覆蓋率并衡量是否完成動(dòng)態(tài)測(cè)試活動(dòng)。圖6為UdpSocket.cpp文件中SocketSndData()函數(shù)的動(dòng)態(tài)測(cè)試圖,圖右上角可以得到該函數(shù)的語(yǔ)句分支覆蓋率都為100%,圖左下角是設(shè)計(jì)并執(zhí)行通過的測(cè)試用例,右下角是用例數(shù)據(jù)的設(shè)計(jì)輸入。
3 結(jié)論
(1)圖形界面框架類單元測(cè)試問題:由于Testbed工具自動(dòng)生成的測(cè)試驅(qū)動(dòng)入口是main()函數(shù),類似于控制臺(tái)程序,當(dāng)遇到圖形框架環(huán)境時(shí)無法完成測(cè)試??蚣茴悾ɡ鏜FC,NI)應(yīng)用程序的執(zhí)行是以事件驅(qū)動(dòng)面向?qū)ο蟮慕Y(jié)構(gòu),定義了很多的API,應(yīng)用程序可以直接調(diào)用。兩種結(jié)構(gòu)是完全不同的,當(dāng)直接使用測(cè)試工具生成測(cè)試驅(qū)動(dòng)時(shí),由于缺少庫(kù)文件,編譯不能通過,無法執(zhí)行測(cè)試用例進(jìn)行測(cè)試。
?。?)被測(cè)單元代碼的必要修改:雖然大多數(shù)編譯環(huán)境和Testbed工具關(guān)聯(lián)在一起,但有一些代碼單元還是不能直接執(zhí)行測(cè)試,代碼在動(dòng)態(tài)測(cè)試之前必須做適當(dāng)?shù)男薷模热缫恍┲袛嗪瘮?shù)、死循環(huán)while()以及Forever等。
(3)測(cè)試人員不能過于依賴測(cè)試工具:自動(dòng)化靜態(tài)分析存在一定的機(jī)械性,測(cè)試人員需逐項(xiàng)進(jìn)行分析確認(rèn)出真正的問題所在,有效的測(cè)試不能簡(jiǎn)單的依靠測(cè)試工具。
參考文獻(xiàn)
[1] 丁旭,崔吉崗,劉春裕.軍用嵌入式軟件結(jié)構(gòu)覆蓋測(cè)試技術(shù)[J].指揮控制與仿真,2008,30(3):120-122.
[2] 李金麒,徐建平.嵌入式系統(tǒng)軟件可靠性設(shè)計(jì)與測(cè)試方法[J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2013,22(1):74-78.
[3] 肖波.通訊系統(tǒng)嵌入式平臺(tái)下的單元測(cè)試技術(shù)研究[D].上海:華東師范大學(xué),2005.
[4] 孫夢(mèng)磷,宋曉秋,巢翌.軟件程序代碼質(zhì)量度量技術(shù)研究[J].計(jì)算機(jī)工程與設(shè)計(jì),2006,27(2):325-327.
[5] 張大林.基于缺陷關(guān)聯(lián)的靜態(tài)分析優(yōu)化[J].軟件學(xué)報(bào),2014,25(2):386-399.
[6] 陽(yáng)凡林,康志忠.基于多維度覆蓋率的軟件測(cè)試動(dòng)態(tài)評(píng)價(jià)方法[J].軟件學(xué)報(bào),2008,21(9):2135-2146.