劉 棟 方麗萍 李國要
(安徽繼遠(yuǎn)檢驗(yàn)檢測技術(shù)有限公司,安徽 合肥 230088)
隨著信息化、智能化進(jìn)程的逐步加深,智能技術(shù)逐漸廣泛應(yīng)用于各類終端設(shè)備。嵌入式系統(tǒng)是智能化終端設(shè)備的核心,能夠?qū)崿F(xiàn)設(shè)備的自動(dòng)運(yùn)行、控制和管理。嵌入式軟件作為嵌入式系統(tǒng)的重要組成部分,也日益受到人們的關(guān)注。嵌入式軟件測試在保障終端設(shè)備功能完備、可靠穩(wěn)定上發(fā)揮著至關(guān)重要的作用。覆蓋率測試是對嵌入式軟件開發(fā)設(shè)計(jì)質(zhì)量的一種有效衡量手段。一般來說,在用例設(shè)計(jì)完整的情況下,軟件覆蓋率的高低能夠較好地反映軟件中存在的問題,軟件覆蓋率越高說明軟件程序設(shè)計(jì)較為完整;軟件覆蓋率低說明軟件程序中存在未被覆蓋的代碼和分支,可以幫助軟件開發(fā)設(shè)計(jì)人員對代碼進(jìn)行分析,未被覆蓋的代碼是冗余無用的還是由于邏輯缺陷未被執(zhí)行的,進(jìn)而有針對性地進(jìn)行缺陷整改,優(yōu)化代碼,提升嵌入式軟件的設(shè)計(jì)質(zhì)量,也提高了終端產(chǎn)品的可靠性和穩(wěn)定性。
嵌入式軟件測試一般是指對終端等智能設(shè)備中能夠執(zhí)行某種或某些特定功能的軟件開展功能、性能、接口、邏輯覆蓋等內(nèi)容的測試。與應(yīng)用軟件測試存在著一定的差異性,嵌入式軟件的測試與硬件的依賴性較強(qiáng),不能脫離硬件設(shè)備,單獨(dú)開展測試[1]。具體存在如下區(qū)別:
(1)嵌入式軟件的功能測試與硬件關(guān)聯(lián)性強(qiáng),對于軟件、硬件模塊的缺陷定位耗時(shí)較長,尤其是對性能的探索性測試需要很大的時(shí)間、精力消耗,定位性能的瓶頸比較困難。
(2)嵌入式軟件測試不具有通用性,測試的環(huán)境需要指定硬件平臺,并且測試往往發(fā)生在宿主機(jī)上,受運(yùn)行環(huán)境的影響,因此,嵌入式軟件測試不僅需要在開發(fā)環(huán)境中開展測試,還要在運(yùn)行環(huán)境中開展測試,這就增加了測試的難度,提高了測試的成本。
(3)嵌入式軟件具有特定性,給嵌入式軟件的自動(dòng)化測試帶來了技術(shù)上的難題。
嵌入式軟件覆蓋率測試是對嵌入式軟件的代碼邏輯和功能結(jié)構(gòu)的正確、適用性進(jìn)行驗(yàn)證的必要環(huán)節(jié)。在進(jìn)行覆蓋率測試時(shí)需要對軟件代碼按照功能模塊進(jìn)行插樁,并依據(jù)相關(guān)的設(shè)計(jì)架構(gòu)和需求進(jìn)行用例的設(shè)計(jì),用例設(shè)計(jì)的原則是盡可能覆蓋更多有效的代碼語句、函數(shù)、分支條件等,能夠貫穿軟件的內(nèi)部邏輯結(jié)構(gòu),只有這樣才可能發(fā)現(xiàn)更深層次的代碼設(shè)計(jì)缺陷和問題[2]。
嵌入式軟件覆蓋率測試一般在單元測試階段進(jìn)行,通過覆蓋率測試可以檢查出嵌入式軟件代碼是否至少執(zhí)行一次,也可以發(fā)現(xiàn)用例的設(shè)計(jì)是否完整有效。在測試過程中,要求覆蓋盡可能多的代碼語句、代碼的分支條件和路徑、代碼的重要函數(shù)等,保障覆蓋率測試的有效性。嵌入式軟件覆蓋測試主要包括:邏輯分支覆蓋、條件覆蓋測試、語句覆蓋測試、函數(shù)的覆蓋測試以及組合覆蓋測試等。
(1)邏輯分支覆蓋:主要是檢查代碼中的所有分支結(jié)構(gòu)是否能夠完全執(zhí)行。在足夠的用例支撐下,盡可能使得代碼中的每個(gè)分支都至少執(zhí)行一次。在實(shí)際測試中,有部分系統(tǒng)的代碼量巨大,要實(shí)現(xiàn)代碼的所有分支覆蓋是比較困難的,因此,對于代碼中能夠?qū)崿F(xiàn)關(guān)鍵功能的分支覆蓋率要測試充分,這樣也提高了測試效率。
(2)條件覆蓋測試:主要是代碼中的判斷語句中存在多個(gè)條件時(shí),要對每個(gè)條件分別設(shè)計(jì)用例,以滿足執(zhí)行后可以獲取多個(gè)不同的結(jié)果。代碼中分支的變化與條件的變化關(guān)聯(lián)程度較小,所以,條件覆蓋充分還要單獨(dú)驗(yàn)證分支的覆蓋是否充分。為了提高測試的效率,條件覆蓋也是保證代碼的關(guān)鍵功能條件覆蓋充分,不造成過多的人力、物力、財(cái)力的浪費(fèi)。
(3)語句覆蓋:語句覆蓋是最基本的覆蓋測試要求,是對代碼中的語句在執(zhí)行中是否被覆蓋的情況統(tǒng)計(jì)。此處的語句指的是代碼中的有效語句,也就是在編譯后,能夠成功執(zhí)行的語句,不包括代碼的注釋語句和無關(guān)語句。語句覆蓋率統(tǒng)計(jì)了代碼中的語句在執(zhí)行中是否至少被執(zhí)行了一次。單純的語句覆蓋測試不能衡量代碼的質(zhì)量,因?yàn)檎Z句覆蓋不會關(guān)心代碼中的分支和條件,有效的代碼覆蓋測試應(yīng)當(dāng)結(jié)合語句、條件和分支覆蓋,進(jìn)行綜合評價(jià)。
(4)函數(shù)覆蓋:函數(shù)覆蓋主要是驗(yàn)證代碼中的各個(gè)函數(shù)在執(zhí)行中是否被覆蓋,每個(gè)關(guān)鍵函數(shù)在執(zhí)行中應(yīng)該充分覆蓋,避免出現(xiàn)函數(shù)未覆蓋而影響代碼的功能執(zhí)行。關(guān)鍵函數(shù)的覆蓋對軟件產(chǎn)品的功能有著直接的影響,因此,函數(shù)覆蓋也是嵌入式軟件覆蓋測試的重點(diǎn)。
(5)其他覆蓋:其他覆蓋主要是指一些多條件覆蓋以及組合覆蓋[3],至于嵌入式軟件代碼覆蓋率測試中,可依據(jù)需求和設(shè)計(jì)架構(gòu),選擇其他或者組合的覆蓋策略,旨在實(shí)現(xiàn)代碼覆蓋充分。在面對大量代碼的嵌入式軟件時(shí),代碼的覆蓋充分就是相對的概念,因?yàn)檫€需要考慮測試的效率,避免大量資源的浪費(fèi),選擇關(guān)鍵的代碼,進(jìn)行語句、分支、條件、函數(shù)等的覆蓋測試,就能夠在一定程度上保障嵌入式軟件的質(zhì)量和測試的有效性。
嵌入式軟件覆蓋率的計(jì)算如下:
其中,嵌入式軟件覆蓋率為C,已執(zhí)行的語句/分支/函數(shù)的代碼的數(shù)目為E,代碼中可執(zhí)行的語句/分支/函數(shù)的代碼總數(shù)N。
覆蓋率測試是一種在嵌入式軟件在單元測試階段進(jìn)行的白盒測試,進(jìn)行覆蓋率測試之前需要依據(jù)測試需求和架構(gòu)說明對用例進(jìn)行充分設(shè)計(jì),設(shè)計(jì)完成后,對被測代碼程序進(jìn)行插樁操作,然后通過Gtest編譯生成可執(zhí)行文件,并運(yùn)行可執(zhí)行文件。此時(shí),嵌入式軟件中接口、功能、性能、邊界值、分支條件等項(xiàng)均已執(zhí)行完成,通過lcov統(tǒng)計(jì)覆蓋率數(shù)據(jù)并寫入文件,最后輸出可視化的覆蓋率報(bào)告。嵌入式軟件覆蓋率測試流程如圖1所示。
圖1 嵌入式軟件覆蓋率測試流程圖
嵌入式軟件的代碼覆蓋率測試是對嵌入式軟件的代碼設(shè)計(jì)有效性的一種評價(jià)依據(jù),在用例充分設(shè)計(jì)的前提下,可以直接展示代碼設(shè)計(jì)的質(zhì)量以及各邏輯結(jié)構(gòu)是否設(shè)計(jì)完全。
目前對于嵌入式軟件的測試工具較多,由于大多數(shù)終端設(shè)備都是基于C/C++語言進(jìn)行設(shè)計(jì)開發(fā)的,因此本文選用針對C/C++的測試工具。一些諸如:testbed、c++test等工具的覆蓋率測試是需要付費(fèi)使用,價(jià)格比較昂貴,對于單元和覆蓋率的測試來說,選取一款開源且測試準(zhǔn)確率高的工具十分必要。
Gtest是Google提供的開源測試框架,功能強(qiáng)大,測試用例編寫也比較簡化,是一種輕量級的測試工具,可以對嵌入式軟件的功能、接口、變量、邊界值等內(nèi)容進(jìn)行驗(yàn)證,實(shí)現(xiàn)嵌入式軟件的單元測試,還可以結(jié)合lcov實(shí)現(xiàn)軟件代碼覆蓋率的統(tǒng)計(jì),支持語句覆蓋率、函數(shù)覆蓋率以及分支覆蓋率的統(tǒng)計(jì);還能提供程序的實(shí)際執(zhí)行信息,包括代碼的執(zhí)行次數(shù)統(tǒng)計(jì),通過html能夠輸出可視化的圖形覆蓋率報(bào)告,使用簡單便捷。
在進(jìn)行嵌入式軟件測試時(shí),測試人員應(yīng)充分閱讀產(chǎn)品需求說明和架構(gòu)設(shè)計(jì)說明,熟悉產(chǎn)品的軟件模塊,以及軟件的功能和運(yùn)行流程,以便更好地開展測試,設(shè)計(jì)測試用例,提高測試的效率。
嵌入式軟件的測試環(huán)境搭建,需要依賴終端設(shè)備。本文搭建的嵌入式軟件測試環(huán)境由測試客戶端、終端設(shè)備、Xshell工具、keil開發(fā)工具、Gtest測試工具、lcov覆蓋率統(tǒng)計(jì)工具等要素構(gòu)成。一般步驟如下:
(1)在測試客戶端中需要安裝Xshell工具,與終端設(shè)備建立連接,實(shí)現(xiàn)嵌入式軟件代碼的上傳與下載。
(2)安裝keil開發(fā)工具,可以實(shí)現(xiàn)代碼的編輯、編譯和插樁,為后面覆蓋率的測試提供了前提條件。
(3)在linux系統(tǒng)下,安裝Gtest工具和lcov工具,進(jìn)行代碼插樁,執(zhí)行完成后,能夠同時(shí)完成單元和覆蓋率的測試,通過查看覆蓋率測試的結(jié)果進(jìn)而對代碼的質(zhì)量進(jìn)行評估。
測試用例設(shè)計(jì)是測試開展的前提條件,只有充分的測試用例設(shè)計(jì)才會使得覆蓋率結(jié)果更為準(zhǔn)確,衡量代碼的質(zhì)量效果更好[4,5]。測試用例設(shè)計(jì)也就是在測試執(zhí)行前確定本次測試需要涉及的內(nèi)容和相關(guān)特性要求,提出基本的測試方法。
測試用例設(shè)計(jì)首先應(yīng)獲取嵌入式軟件設(shè)計(jì)的架構(gòu)和需求,在充分分析設(shè)計(jì)架構(gòu)和需求的前提下,研究軟件的功能模塊,并依據(jù)模塊,進(jìn)行用例的設(shè)計(jì)。用例設(shè)計(jì)在兼顧代碼重要模塊的同時(shí),還要延伸用例設(shè)計(jì)的思維,覆蓋正反向用例、邊界用例等。測試用例的基本要素包括:名稱和標(biāo)識、測試依據(jù)、測試的環(huán)境要素及要求、測試的輸入輸出、期望結(jié)果、結(jié)果的評判依據(jù)等。
測試用例的設(shè)計(jì)一般流程如下:
(1)查看嵌入式軟件的設(shè)計(jì)需求及架構(gòu),測試人員應(yīng)充分了解軟件的模塊及架構(gòu),整理軟件的功能模塊,并依據(jù)功能模塊設(shè)計(jì)測試用例。
(2)選取涉及功能模塊的關(guān)鍵代碼,加入Gtest相關(guān)頭文件,使用工具斷言來實(shí)現(xiàn)測試是否符合預(yù)期結(jié)果。
(3)依次設(shè)計(jì)好關(guān)鍵功能模塊的測試用例,滿足測試的需求。
本文在嵌入式軟件基本測試環(huán)境完備情況下,開展覆蓋率測試的一般流程如下:
(1)安裝Xshell工具,運(yùn)行和配置ip,連接終端設(shè)備,通過xftp下載獲取終端設(shè)備的嵌入式軟件代碼。
(2)依據(jù)產(chǎn)品的需求及架構(gòu)設(shè)計(jì)文件,熟悉產(chǎn)品的模塊功能和結(jié)構(gòu),安裝keil工具,導(dǎo)入源代碼文件,并對應(yīng)進(jìn)行編譯和插樁操作。
(3)下載Gtest和lcov安裝包,執(zhí)行tar命令解壓后進(jìn)行安裝,安裝完成后查看工具的版本號是否安裝成功。
(4)將插樁后的代碼按照軟件功能模塊,將其劃分為多個(gè)后綴為.c/.cpp的文件,并加入測試用例執(zhí)行腳本后形成待執(zhí)行文件。
(5)使用Gtest和lcov進(jìn)行嵌入式軟件的功能和覆蓋率的測試,將待執(zhí)行的.c/.cpp文件通過Gtest工具編譯,鏈接lGtest庫和lpthread庫,生成可執(zhí)行文件,執(zhí)行文件可完成單元測試的結(jié)果驗(yàn)證。
(6)添加-fprofile-arcs和-ftest-coverage參數(shù)編譯程序,生成可執(zhí)行程序和.gcno文件,運(yùn)行可執(zhí)行文件,生成.gcda文件,通過lcov收集.gcda文件中的信息,并寫入.info文件,在輸入genhtml指令后生成的一個(gè)包含有.html文件的文件夾,其中.html文件即為覆蓋率報(bào)告。
測試流程執(zhí)行完成后,會生成測試結(jié)果。執(zhí)行單元測試功能和接口等測試時(shí),每次執(zhí)行完成后會出現(xiàn)執(zhí)行后的結(jié)果,若結(jié)果中出現(xiàn)報(bào)錯(cuò)信息,顯示期望值與實(shí)際值的差異,測試人員可以依據(jù)錯(cuò)誤提示,快速定位失敗信息,并及時(shí)修改。若用例測試全部通過,也就說明沒有任何報(bào)錯(cuò)。統(tǒng)計(jì)結(jié)果一般包括:該用例包括的用例個(gè)數(shù)、執(zhí)行通過的測試用例個(gè)數(shù)、執(zhí)行失敗的測試用例個(gè)數(shù)以及失敗用例序號等。執(zhí)行覆蓋率測試用例后,會生成覆蓋率的結(jié)果報(bào)告,打開覆蓋率報(bào)告,即可查看覆蓋率的統(tǒng)計(jì)信息以及詳細(xì)的語句覆蓋、分支覆蓋的代碼信息,如圖2所示。
圖2 嵌入式軟件覆蓋率報(bào)告結(jié)果
可在覆蓋率報(bào)告中展開詳細(xì)信息,在文件或函數(shù)的視圖下,可顯示代碼的具體行數(shù)。報(bào)告中的代碼前數(shù)字表示該語句被執(zhí)行的次數(shù),代碼語句前的“+”“-”符號,代表分支的個(gè)數(shù),其中,“+”號表示該分支在執(zhí)行中已經(jīng)被覆蓋,“-”號表示該分支在執(zhí)行中未被覆蓋,且以紅色標(biāo)識。
嵌入式軟件覆蓋率報(bào)告分別顯示語句覆蓋率、函數(shù)覆蓋率、分支覆蓋率的統(tǒng)計(jì)結(jié)果,代碼中語句、函數(shù)、分支已經(jīng)執(zhí)行的個(gè)數(shù)以及總數(shù)。在覆蓋率測試結(jié)果中,如果出現(xiàn)覆蓋率結(jié)果小于100%,則可能出現(xiàn)兩種情況,要分別檢查排除情況。
(1)用例設(shè)計(jì)不夠充分,可以從測試覆蓋率的結(jié)果來檢驗(yàn)用例的設(shè)計(jì),覆蓋率結(jié)果中出現(xiàn)某一分支的結(jié)果中有標(biāo)記為“-”,查看對應(yīng)的分支是否用例已經(jīng)覆蓋,未發(fā)現(xiàn)用例覆蓋,則補(bǔ)充對應(yīng)用例,再次執(zhí)行測試,若覆蓋率結(jié)果完全覆蓋,則表明用例測試充分,若仍未完全覆蓋,則對應(yīng)尋找軟件代碼中的設(shè)計(jì)缺陷問題,記錄缺陷,并與研發(fā)人員進(jìn)行溝通,改進(jìn)代碼,保障代碼的質(zhì)量。
(2)代碼本身的質(zhì)量缺陷,在用例設(shè)計(jì)充分的前提下,代碼覆蓋率結(jié)果仍有未覆蓋,則需尋找代碼的缺陷,該路徑存在執(zhí)行失敗的問題。
嵌入式軟件覆蓋率測試,可以衡量代碼的質(zhì)量和用例設(shè)計(jì)的充分性,在測試人員對用例設(shè)計(jì)充分的前提下,就能直接反映出代碼本身的質(zhì)量,對嵌入式軟件的安全可靠提供了保障。
嵌入式軟件在測試中除了關(guān)注軟件本身的功能、接口、性能的測試結(jié)果,還需要關(guān)注軟件的覆蓋率情況,軟件覆蓋率在測試用例充分設(shè)計(jì)的前提下,可以直接反映出軟件代碼的質(zhì)量,定位軟件代碼的缺陷問題,也可以幫助測試人員快速查找用例設(shè)計(jì)的缺失問題,保障用例設(shè)計(jì)的充分性。因此,嵌入式軟件覆蓋率測試是十分必要的。
本文在充分考慮測試資源的消耗以及測試成本的壓縮上,選用Gtest和lcov完成嵌入式軟件的單元和覆蓋率測試,闡述了嵌入式軟件覆蓋率測試的方法和工具,并對測試的環(huán)境搭建、用例設(shè)計(jì)、詳細(xì)流程以及報(bào)告分析等方面進(jìn)行詳細(xì)分析,提高了測試人員的測試效率,快速定位缺陷,也幫助研發(fā)人員發(fā)現(xiàn)嵌入式軟件的設(shè)計(jì)缺陷,指導(dǎo)進(jìn)行缺陷的修改,從整體上保障了嵌入式軟件的質(zhì)量。