淺談軟件測(cè)試嵌入式單元測(cè)試技能
單元測(cè)試是在軟件開(kāi)發(fā)過(guò)程中要進(jìn)行的最低級(jí)別的測(cè)試活動(dòng),在單元測(cè)試活動(dòng)中,軟件的獨(dú)立單元將在與程序的其他部分相隔離的情況下進(jìn)行測(cè)試。 單元測(cè)試不僅僅是作為無(wú)錯(cuò)編碼一種輔助手段在一次性的開(kāi)發(fā)過(guò)程中使用,單元測(cè)試必須是可重復(fù)的,無(wú)論是在軟件修改,或是移植到新的運(yùn)行環(huán)境的過(guò)程中。因此,所有的測(cè)試都必須在整個(gè)軟件系統(tǒng)的生命周期中進(jìn)行維護(hù)。
對(duì)嵌入式系統(tǒng)軟件執(zhí)行測(cè)試是一項(xiàng)很有挑戰(zhàn)性的工作。因?yàn)榍度胧较到y(tǒng)的軟件開(kāi)發(fā)平臺(tái)和最終運(yùn)行平臺(tái)是完全不一樣的兩個(gè)平臺(tái),開(kāi)發(fā)者不可能在其運(yùn)行平臺(tái)上像在桌面環(huán)境那樣執(zhí)行測(cè)試程序。這些差異可以表現(xiàn)在這多個(gè)方面。在軟件開(kāi)發(fā)的時(shí)候目標(biāo)硬件平臺(tái)可能還沒(méi)有準(zhǔn)備好,軟件工程師在訪問(wèn)硬件時(shí)可能會(huì)很麻煩,在開(kāi)發(fā)環(huán)境下模擬整個(gè)系統(tǒng)存在困難性等。
本文闡述了單元測(cè)試在嵌入式系統(tǒng)軟件開(kāi)發(fā)流程中的作用以及其如何幫助開(kāi)發(fā)者處理上述疑問(wèn)。簡(jiǎn)要地講,它提升了樁函數(shù)在宿主環(huán)境下或者仿真器中的作用。這使軟件工程師在代碼編寫(xiě)完畢之后就可以立即對(duì)其執(zhí)行 驗(yàn)證,即使此時(shí)目標(biāo)硬件系統(tǒng)還沒(méi)有準(zhǔn)備好或暫時(shí)不能執(zhí)行測(cè)試。這樣,絕大部分的潛藏在程序中的邏輯疑問(wèn)都能夠在早期被發(fā)覺(jué),軟件工程師就可以迅捷地修正這些疑問(wèn),而目標(biāo)平臺(tái)上的測(cè)試就可以注重于檢測(cè)軟硬件接口方面的疑問(wèn)。
為何要對(duì)嵌入式系統(tǒng)軟件執(zhí)行單元測(cè)試?
單元測(cè)試是檢查嵌入式系統(tǒng)軟件缺陷的最有效的一種要領(lǐng),更確切而言也即在宿主機(jī)環(huán)境下或在仿真器上執(zhí)行 的API測(cè)試。這能使測(cè)試盡早開(kāi)始并且最大程度地降低了測(cè)試工作對(duì)目標(biāo)硬件平臺(tái)的依賴性。嵌入式系統(tǒng)軟件的單元測(cè)試的一個(gè)前提是能夠讓軟件獨(dú)立于硬件執(zhí)行 測(cè)試,這是由樁函數(shù)對(duì)目標(biāo)硬件平臺(tái)的模擬而實(shí)現(xiàn)的。在這種情況下,代碼的絕大多數(shù)功能性測(cè)試都能夠獨(dú)立于目標(biāo)硬件系統(tǒng)執(zhí)行 測(cè)試。這對(duì)嵌入式系統(tǒng)開(kāi)發(fā)者而言有以下主要優(yōu)點(diǎn)。
1. 單元測(cè)試能讓開(kāi)發(fā)者在目標(biāo)硬件平臺(tái)準(zhǔn)備好之前就開(kāi)始測(cè)試周期,開(kāi)發(fā)者可以直接在宿主開(kāi)發(fā)環(huán)境下開(kāi)始原始測(cè)試(而不須要目標(biāo)硬件平臺(tái))。早期測(cè)試能夠?yàn)殚_(kāi)發(fā)團(tuán)隊(duì)發(fā)覺(jué)并修正缺陷提供盡可能充足的時(shí)間。此外,早期測(cè)試還能將測(cè)試工作較平均地分配于產(chǎn)品開(kāi)發(fā)的各個(gè)階段中,從而防止將所有的測(cè)試工作留到產(chǎn)品揭曉之前才執(zhí)行 ,為開(kāi)發(fā)團(tuán)隊(duì)爭(zhēng)取了充足的時(shí)間。
2. 單元測(cè)試采取一種“各個(gè)擊破”的策略,允許用戶將復(fù)雜的系統(tǒng)分為相對(duì)較基本的準(zhǔn)獨(dú)立系統(tǒng)執(zhí)行 測(cè)試。測(cè)試工具能夠管理模塊之間的關(guān)聯(lián)性并運(yùn)用樁函數(shù)來(lái)模擬這些模塊的行為。
圖1:運(yùn)用樁函數(shù),開(kāi)發(fā)者可以模擬真實(shí)環(huán)境和程序之間的相互影響對(duì)程序的某個(gè)模塊執(zhí)行 測(cè)試,而不須要目標(biāo)硬件平臺(tái)以及暫時(shí)還未完成的其它代碼模塊。在測(cè)試環(huán)境中,樁函數(shù)充當(dāng)了為待測(cè)模塊提供外部關(guān)聯(lián)性橋梁的作用。
在代碼修改流程中保衛(wèi)代碼完整性
復(fù)雜系統(tǒng)的開(kāi)發(fā)者最大的煩惱就是不能確定對(duì)代碼的修改能不能改動(dòng)或破壞了程序的既有功能性。為了打消這些顧慮,用戶可以建立一個(gè)基準(zhǔn)單元測(cè)試套件來(lái)捕捉代碼的既有功能性。如果用戶希望檢查相對(duì)于基準(zhǔn)單元測(cè)試套件的改動(dòng),只須要對(duì)修改過(guò)的代碼定期地運(yùn)行該測(cè)試套件即可。因?yàn)閱卧獪y(cè)試能夠獨(dú)立地測(cè)試系統(tǒng)的某些代碼,所以這樣一組回歸測(cè)試套件可以持續(xù)地執(zhí)行而無(wú)論目標(biāo)硬件平臺(tái)準(zhǔn)備好與否。這種測(cè)試并不排斥對(duì)整個(gè)程序執(zhí)行 測(cè)試的分離回歸測(cè)試套件。
這樣的測(cè)試套件作為變更檢測(cè)完全能夠讓用戶確保如果無(wú)意間破壞了既有功能性能夠被立即告知。當(dāng)目標(biāo)硬件平臺(tái)準(zhǔn)備好后,用戶可以直接用宿主環(huán)境下的測(cè)試來(lái)驗(yàn)證代碼能不能會(huì)在實(shí)際的目標(biāo)硬件平臺(tái)上正確地運(yùn)行。雖然代碼在宿主環(huán)境下執(zhí)行 了回歸測(cè)試,但是在目標(biāo)硬件平臺(tái)上還是須要執(zhí)行 一定的自動(dòng)系統(tǒng)測(cè)試。
驗(yàn)證不正確處理
由于消費(fèi)類(lèi)產(chǎn)品的不正確處理可靠性需求的不同,所以系統(tǒng)測(cè)試情景變得更加復(fù)雜了。因?yàn)椴荒芫_地預(yù)測(cè)其運(yùn)用情況,所以系統(tǒng)的設(shè)計(jì)和測(cè)試都不能基于某個(gè)特定的情況。
相反這些系統(tǒng)必須經(jīng)過(guò)廣泛地不正確以及未預(yù)期輸入的驗(yàn)證,以保證這些輸入能夠被正確地處理。
運(yùn)用含有樁函數(shù)的單元測(cè)試同樣能夠大大地簡(jiǎn)化不正確測(cè)試流程。總的而言,在運(yùn)用 程序這一層級(jí)來(lái)測(cè)試不正確條件是一件相當(dāng)耗時(shí)的事,因?yàn)閷⒊绦蛑糜?ldquo;正確的不正確狀態(tài)”須要準(zhǔn)備相對(duì)復(fù)雜的輸入數(shù)據(jù)并且同時(shí)要求程序在其大量的可能狀態(tài)中處于相應(yīng)的狀態(tài)。與之形成鮮明比較的是,運(yùn)用 “不正確模擬”要領(lǐng)來(lái)對(duì)某些函數(shù)執(zhí)行 不正確處理測(cè)試則要基本得多。
例如,測(cè)試一個(gè)含有輸入數(shù)據(jù)不正確處理機(jī)制的測(cè)試是相當(dāng)基本的:
- float signalToNoiseRatio (float signal,float noise,MODE mode)
- {
- if (MODE_MEASUREMENT == mode)
- {
- …
- if (signal < 0 noise < 0)
- {
- handle_bad_data();
- }
- }
- }
- float signalToNoiseRatio (float signal,float noise,MODE mode)
- {
- if (MODE_MEASUREMENT == mode)
- {
- …
- if (signal < 0 noise < 0)
- {
- handle_bad_data();
- }
- }
- }
在這種情況下,在測(cè)試程序中對(duì)handle_bad_data()函數(shù)的調(diào)用是很基本的,因?yàn)闇y(cè)試該語(yǔ)句能不能受程序輸入數(shù)據(jù)控制是很基本的。
盡管如此,很多情況下控制語(yǔ)句并不直接受控于函數(shù)接口,而是取決于系統(tǒng)處于的特定狀態(tài),如下例所示。將系統(tǒng)置于該不正確狀態(tài)可能會(huì)相當(dāng)復(fù)雜,甚至可能牽扯到讓設(shè)備接口處于某些特定狀態(tài),所以測(cè)試用例中的這個(gè)條件就須要通過(guò)模擬來(lái)實(shí)現(xiàn)。
- float shutDown ()
- {
- if (uploadingData())
- {
- userMessage (“Cannot execute shutdown while uploading data”);
- recoverShutDown();
- }
- else
- {
- // shut down indeed
- }
- }
運(yùn)用支持“智能樁函數(shù)”(smart stubs)的高級(jí)測(cè)試工具,對(duì)于復(fù)雜不正確條件的測(cè)試比其它要領(lǐng)就基本了很多。“智能樁函數(shù)”允許通過(guò)原始函數(shù)的樁函數(shù)以及通過(guò)實(shí)現(xiàn)某些必要的特定功能的要領(lǐng)來(lái)執(zhí)行代碼。實(shí)際而言,當(dāng)被測(cè)程序明顯沒(méi)有處于不正確狀態(tài)時(shí),其相應(yīng)待測(cè)函數(shù)將被調(diào)用以模擬不正確實(shí)際發(fā)生的情況,這就是“不正確模擬”的意義。在上述例子中,對(duì)不正確處理函數(shù)uploadingData()的測(cè)試須要其樁函數(shù)以保證至少讓其返回一次“真”。
一些值得考慮的疑問(wèn)
在宿主環(huán)境下執(zhí)行 測(cè)試可能意味著用以建立代碼的編譯器和目標(biāo)系統(tǒng)編譯器不同。如果交叉編譯器提供商同時(shí)提供用在宿主環(huán)境下的編譯器(例如Green Hills Software的本地編譯器),則可以直接運(yùn)用。如果沒(méi)有,則可以運(yùn)用支持大多數(shù)平臺(tái)的GNU Compiler Collection(GCC)。雖然保證代碼在宿主編譯器和目標(biāo)編譯器上的一致性會(huì)對(duì)維護(hù)成本有些許的提升,但是與早期測(cè)試對(duì)整個(gè)項(xiàng)目帶來(lái)的優(yōu)點(diǎn)相比卻是很合算的。
單元測(cè)試不大可能發(fā)覺(jué)因同步不正確造成的運(yùn)用 程序級(jí)的不正確條件或者與實(shí)際設(shè)備接口的不正確。盡管如此,在嵌入式系統(tǒng)的開(kāi)發(fā)流程中,單元測(cè)試能幫助開(kāi)發(fā)者盡早地發(fā)覺(jué)很多類(lèi)不正確,所以提高了系統(tǒng)整體開(kāi)發(fā)效率并且消除了測(cè)試瓶頸。
運(yùn)用 C++test來(lái)自動(dòng)化單元測(cè)試流程
用戶可以運(yùn)用 Parasoft C++test來(lái)自動(dòng)化對(duì)嵌入式系統(tǒng)軟件的測(cè)試。
Parasoft C++test是一套經(jīng)廣泛驗(yàn)證的最佳編碼實(shí)踐的自動(dòng)化處理方案,它能有效地提高軟件開(kāi)發(fā)團(tuán)隊(duì)的開(kāi)發(fā)效率以及軟件的質(zhì)量。C++test能幫助用戶執(zhí)行 編碼策略增強(qiáng)、靜態(tài)代碼分析、徹底代碼走查以及單元和組件測(cè)試,從而為用戶保證其C以及C++代碼按預(yù)期運(yùn)行提供一個(gè)實(shí)際可行的要領(lǐng)。C++test可以在桌面環(huán)境下的主流IDE(包括Wind River Workbench以及Eclipse)以及回歸測(cè)試流程中的命令行中以批處理的方式運(yùn)行。C++test集成了Parasoft的GRS報(bào)告系統(tǒng),它能提供一個(gè)基于Web交互界面的報(bào)表并為用戶提供向下挖掘(drill-down)功能,基于C++test報(bào)告的這些結(jié)果,開(kāi)發(fā)團(tuán)隊(duì)實(shí)時(shí)把握項(xiàng)目狀態(tài)和趨勢(shì)以及其它關(guān)鍵指標(biāo)。
對(duì)于嵌入式以及交叉開(kāi)發(fā)而言,C++test可以在基于宿主環(huán)境和目標(biāo)環(huán)境下執(zhí)行代碼分析以及數(shù)據(jù)流分析。在宿主環(huán)境中,開(kāi)發(fā)者可以通過(guò)C++test的編碼策略增強(qiáng)、靜態(tài)代碼分析、徹底代碼走查以及單元和組件測(cè)試模塊來(lái)對(duì)代碼執(zhí)行 “隨時(shí)測(cè)試”式的驗(yàn)證以及回歸測(cè)試。被測(cè)代碼的外部依賴性被樁函數(shù)自動(dòng)地取代,樁函數(shù)能真實(shí)地模擬硬件以及其它代碼在實(shí)際運(yùn)行中的表現(xiàn)。
圖2:Wind River Workbench中的C++test插件能為其用戶提供一個(gè)簡(jiǎn)便的要領(lǐng)來(lái)運(yùn)用 C++test執(zhí)行 完整的代碼分析和單元測(cè)試。
通過(guò)擴(kuò)展的基于宿主環(huán)境的測(cè)試,C++test能讓用戶在某個(gè)模塊代碼完成后立即對(duì)其執(zhí)行 測(cè)試,即使此時(shí)目標(biāo)環(huán)境還未準(zhǔn)備好或不能執(zhí)行 測(cè)試。這樣,絕大部分的潛藏在程序中的邏輯疑問(wèn)都能夠在早期被發(fā)覺(jué),從而讓開(kāi)發(fā)者修正這些不正確變得十分迅捷,而在目標(biāo)硬件平臺(tái)上的測(cè)試則能更加注重于驗(yàn)證軟硬件接口疑問(wèn)。此外,基于宿主環(huán)境的測(cè)試相對(duì)于目標(biāo)系統(tǒng)而言更加容易自動(dòng)運(yùn)行和維護(hù),這使得用戶可以不用其它嵌入式開(kāi)發(fā)工具就可以驗(yàn)證相對(duì)平臺(tái)獨(dú)立的代碼正確性。
當(dāng)開(kāi)發(fā)者在仿真器或?qū)嶋H目標(biāo)硬件平臺(tái)上執(zhí)行 測(cè)試時(shí),在宿主環(huán)境下生成和優(yōu)化過(guò)的測(cè)試套件可以被重用來(lái)驗(yàn)證軟件在目標(biāo)硬件上的功能性。先前的樁函數(shù)這時(shí)可以用實(shí)際代碼或者系統(tǒng)接口來(lái)代替從而完成完整系統(tǒng)的測(cè)試,而不須要修改測(cè)試代碼。C++test同時(shí)還提供一個(gè)內(nèi)建功能來(lái)自動(dòng)捕捉執(zhí)行測(cè)試輸出以及將其轉(zhuǎn)變成后續(xù)回歸測(cè)試時(shí)的“黃金”數(shù)據(jù)集。
C++test讓整個(gè)測(cè)試流程自動(dòng)執(zhí)行 ,包括測(cè)試用例生成、交叉編譯、部署、執(zhí)行以及將測(cè)試結(jié)果(包括覆蓋率指標(biāo))導(dǎo)入GUI。測(cè)試可以通過(guò)GUI交互地執(zhí)行 或者通過(guò)命令行自動(dòng)執(zhí)行,以及以批處理的方式執(zhí)行 的回歸測(cè)試。在交互模式下,用戶可以對(duì)單個(gè)模塊或者一組代碼執(zhí)行 測(cè)試,從而讓調(diào)試和驗(yàn)證都變得更基本。在批處理模式下,測(cè)試可以針對(duì)用戶提供的代碼或者根據(jù)文件名字或在硬盤(pán)中的位置來(lái)執(zhí)行 。
同時(shí),C++test還支持將其執(zhí)行順序執(zhí)行 完全的用戶自定義。除了內(nèi)建的自動(dòng)化測(cè)試,用戶還可以引入自定義測(cè)試腳本以及通過(guò)shell命令將測(cè)試工具根據(jù)代碼具體結(jié)構(gòu)和測(cè)試環(huán)境執(zhí)行 自定義。C++test的運(yùn)行庫(kù)也可以被自定義并且針對(duì)不同的目標(biāo)操作系統(tǒng)執(zhí)行 交叉編譯。這種無(wú)可比擬的靈活性能夠任意實(shí)現(xiàn)其希望的測(cè)試流程而不須要預(yù)設(shè)工具的功能。
圖3:C++test的可自定義工作流程讓用戶可以根據(jù)代碼的構(gòu)造來(lái)執(zhí)行 測(cè)試,然后運(yùn)用這個(gè)測(cè)試套件在目標(biāo)硬件環(huán)境下測(cè)試其功能性和可靠性。
嵌入式開(kāi)發(fā)支持的單元測(cè)試
真實(shí)的單元(函數(shù)/類(lèi))和組件測(cè)試
自動(dòng)生成C或C++格式的測(cè)試套件
支持?jǐn)?shù)據(jù)源
單一測(cè)試或者任意測(cè)試的任意組合方式的交互執(zhí)行
捕捉實(shí)際測(cè)試結(jié)果后自動(dòng)生成回歸測(cè)試套件
宿主平臺(tái)和目標(biāo)平臺(tái)的統(tǒng)一測(cè)試環(huán)境
測(cè)試流程完全可自定義并提供運(yùn)行時(shí)支持
語(yǔ)句、代碼塊、分支/條件以及路徑指標(biāo)覆蓋率分析
提供HTML和XML格式的測(cè)試結(jié)果報(bào)告
支持GUI/桌面環(huán)境以及命令行方式
支持的目標(biāo)編譯器
Wind River GCC 3.4.x和DIAB 5.4+
GCC 2.95.x – 4.1交叉編譯器
Green Hills 4.0.x
【編輯推薦】