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