測(cè)試是傳統(tǒng)軟體開發(fā)的最后一步。整個(gè)軟體開發(fā)過程,需要收集要求、進(jìn)行高層次的設(shè)計(jì)、詳細(xì)設(shè)計(jì)、製作程式碼、進(jìn)行部份單元測(cè)試,然后整合,最后才開始最終測(cè)試。
最佳的開發(fā)實(shí)踐應(yīng)包含程式碼檢查這個(gè)步驟。然而程式碼檢查一般只能找出70%的系統(tǒng)錯(cuò)誤,因此完美的測(cè)試環(huán)節(jié)絕對(duì)必不可少。測(cè)試就像個(gè)復(fù)式記帳系統(tǒng),可以確保將缺陷扼殺在最終推出的產(chǎn)品之前。
在所有其它的工程實(shí)踐中,測(cè)試都被視為基本環(huán)節(jié)。比如,在美國(guó),每一座聯(lián)邦政府出資修建的橋都必須經(jīng)過大量的風(fēng)洞測(cè)試。而在軟體領(lǐng)域,測(cè)試并沒有很受重視。儘管測(cè)試是所有工程實(shí)踐準(zhǔn)則的關(guān)鍵部份,但編寫測(cè)試程式卻感覺是在浪費(fèi)時(shí)間。好在嵌入式系統(tǒng)設(shè)計(jì)界內(nèi)的許多領(lǐng)域已經(jīng)將測(cè)試作為其工作的核心部份,他們認(rèn)識(shí)到將這個(gè)關(guān)鍵步驟放在計(jì)畫末期極不明智,因而主張同步地編寫測(cè)試程式和應(yīng)用程式。
嵌入式系統(tǒng)軟體測(cè)試在諸多方面都與應(yīng)用軟體測(cè)試一樣。不過,應(yīng)用測(cè)試與嵌入式系統(tǒng)測(cè)試之間還是存在一些重要差異。嵌入式開發(fā)人員一般會(huì)用到基于硬體的測(cè)試工具,而這類工具通常不會(huì)用于應(yīng)用開發(fā)過程中。此外,嵌入式系統(tǒng)一般都有些獨(dú)一無二的特性,這些特性應(yīng)該在測(cè)試計(jì)劃中得以體現(xiàn)。本文將介紹測(cè)試和測(cè)試案例開發(fā)的基礎(chǔ)知識(shí),并指出整個(gè)嵌入式系統(tǒng)測(cè)試工作的特有細(xì)節(jié)。
何時(shí)測(cè)試以及如何測(cè)試
從圖1可以看出,在可行的條件下,測(cè)試應(yīng)盡早展開。一般來講,最早的測(cè)試是由最初的開發(fā)人員進(jìn)行的模組或單元測(cè)試。遺憾的是,開發(fā)人員大多對(duì)如何建構(gòu)一整套測(cè)試?yán)桃赃M(jìn)行測(cè)試所知不足。由于精心設(shè)計(jì)測(cè)試?yán)掏ǔV钡秸蠝y(cè)試時(shí)才能使用,因此許多在單元測(cè)試過程中就能找出的缺陷直到整合測(cè)試時(shí)才會(huì)被發(fā)現(xiàn)。比如,硅谷的一家大型網(wǎng)路設(shè)備廠商為找出其軟體整合問題的關(guān)鍵塬因,進(jìn)行了一項(xiàng)研究。這家廠商發(fā)現(xiàn),在計(jì)畫整合階段找出的缺陷中,有70%是由在整合之前從沒被執(zhí)行過的程式所產(chǎn)生的。
圖1:改正問題的成本。
單元測(cè)試:開發(fā)人員在單獨(dú)進(jìn)行模組級(jí)測(cè)試時(shí)一般是編寫存根程式碼(stub code)取代余下的系統(tǒng)軟硬體。在開發(fā)週期的這個(gè)環(huán)節(jié),測(cè)試主要側(cè)重于程式碼的邏輯性能。
通常,開發(fā)人員會(huì)分別使用某些平均值、高值或低值、以及某些超出範(fàn)圍的值(以測(cè)試程式碼的異常處理功能)進(jìn)行測(cè)試。但這些基于‘黑盒子’的測(cè)試僅能對(duì)模組中整個(gè)程式碼的一部份進(jìn)行測(cè)試。
回歸測(cè)試:測(cè)試不應(yīng)是一勞永逸的。每次修改程式后都應(yīng)該重新進(jìn)行測(cè)試,以確保這些更改不會(huì)無意中‘誤傷’某些不相關(guān)的行為。
稱為回歸測(cè)試的這類測(cè)試,一般是透過測(cè)試腳本自動(dòng)進(jìn)行的。比如,如果你設(shè)計(jì)了一組100個(gè)輸入/輸出(I/O)測(cè)試,回歸測(cè)試腳本會(huì)自動(dòng)執(zhí)行這100個(gè)測(cè)試,然后將輸出與一組‘黃金標(biāo)準(zhǔn)’輸出進(jìn)行對(duì)比。每次對(duì)程式碼的任何部份進(jìn)行修改時(shí),都要對(duì)包含被修改程式碼的整個(gè)程式執(zhí)行整套回歸測(cè)試程式包,以確維修改過程中不會(huì)‘誤傷’其余程式碼。
測(cè)試什么
因?yàn)闆]有一個(gè)實(shí)際的測(cè)試集可以證明一個(gè)程式是正確的,因此關(guān)鍵問題變成了哪個(gè)測(cè)試子集最有可能檢測(cè)到最多的錯(cuò)誤。選擇合適的測(cè)試?yán)痰膯栴}被稱為測(cè)試?yán)淘O(shè)計(jì)。雖然存在數(shù)十種測(cè)試案例的設(shè)計(jì)方法,但它們通??蓺w為兩種截然不同的方法:功能測(cè)試和覆蓋測(cè)試。
功能測(cè)試(也稱為黑盒子測(cè)試)選擇可評(píng)估實(shí)現(xiàn)與需求規(guī)格符合程度的測(cè)試。覆蓋測(cè)試(也稱為白盒子測(cè)試)選擇可執(zhí)行程式碼某些部份的測(cè)試?yán)獭#ㄟ^后,將詳細(xì)討論這兩種方法。)
這兩種測(cè)試都是對(duì)嵌入式設(shè)計(jì)進(jìn)行嚴(yán)格測(cè)試所必須的。其中,覆蓋測(cè)試表示程式碼的穩(wěn)定性,所以這種測(cè)試是用于已經(jīng)完成或?qū)⒔瓿傻漠a(chǎn)品的。另一方面,可在編寫要求文件時(shí),同時(shí)編寫功能測(cè)試。
事實(shí)上,從功能測(cè)試開始入手,可以大幅地降低重復(fù)勞動(dòng)和重寫測(cè)試案例的工作。因此,在我看來,要先考慮功能測(cè)試。
每個(gè)人都同意先編寫功能測(cè)試這個(gè)觀點(diǎn),有人認(rèn)為,功能測(cè)試在系統(tǒng)整合階段(而不是在單元測(cè)試時(shí))最有用。以下是整合功能測(cè)試和覆蓋測(cè)試方法的一個(gè)簡(jiǎn)單處理流程:
1.找出哪些功能未被功能測(cè)試完全覆蓋。
2.找出每個(gè)功能的哪些部份沒被執(zhí)行。
3.找出需要哪些額外的覆蓋測(cè)試。
4.執(zhí)行新增的額外測(cè)試。
5.重復(fù)以上步驟。
何時(shí)停止測(cè)試?
最通用的停止標(biāo)準(zhǔn)(按可靠性排序)如下:
1.老板命令停止測(cè)試
2.新的測(cè)試週期找到的新缺陷少于X個(gè)
3.在沒有發(fā)現(xiàn)任何新缺陷的情況下已經(jīng)滿足了某個(gè)覆蓋閥限
無論你多么徹底地測(cè)試了程式,都無法保證找出所有缺陷。這引發(fā)了另一個(gè)有趣的問題:你可容忍多少缺陷?假設(shè)在極端軟體壓力測(cè)試過程中,你發(fā)現(xiàn)系統(tǒng)每進(jìn)行大約20小時(shí)的測(cè)試就會(huì)鎖定。你仔細(xì)地檢查程式,但是仍無法找出這個(gè)錯(cuò)誤的根源。這個(gè)時(shí)候你應(yīng)該提供產(chǎn)品嗎?
多少測(cè)試才‘足夠好’?這個(gè)我說不好。但遵循一些久經(jīng)時(shí)間考驗(yàn)的規(guī)則總是好的:“如果方法Z預(yù)估Y行程式碼中的缺陷少于X個(gè),那么就可放心地發(fā)佈程式了?!币苍S有一天會(huì)出現(xiàn)這種標(biāo)準(zhǔn)。編程產(chǎn)業(yè)仍然相對(duì)年輕,還達(dá)不到類似建筑業(yè)那樣的成熟度。
許多厚厚的建筑手冊(cè)和大本規(guī)格是多年經(jīng)驗(yàn)的結(jié)晶,它們可為建筑師、土木工程師和結(jié)構(gòu)工程師提供按工期在預(yù)算內(nèi)、建造一棟安全建筑所需的全部資訊。偶爾雖仍會(huì)有建筑倒塌,但畢竟很少見。在編程產(chǎn)業(yè)制訂出類似標(biāo)準(zhǔn)前,“多少測(cè)試才足夠?”就是個(gè)主觀判斷問題。
選擇測(cè)試案例
在理想情況下,你可能想要測(cè)試程式中每一個(gè)可能的行為。這意味著每一種可能的輸入組合或者每一種可能的判定路徑至少測(cè)試一次。
這是個(gè)崇高但完全不切實(shí)際的目標(biāo)。比如,Glen Ford Myers在其《軟體測(cè)試的藝術(shù)》一書中就描述了一個(gè)只用五個(gè)判定條件就可有1014個(gè)不同執(zhí)行路徑的小程式。他指出,如果你能夠每五分鐘就能編寫、執(zhí)行并驗(yàn)證一個(gè)測(cè)試?yán)痰脑挘敲慈鎻氐椎販y(cè)試完這個(gè)小程式需要10億年時(shí)間。
顯然,理想的狀況是無法實(shí)現(xiàn)的,因此你必須採用接近這種理想狀況的標(biāo)準(zhǔn)。如你所見,功能測(cè)試與覆蓋測(cè)試相結(jié)合可以提供合理的次優(yōu)選擇方案?;痉椒ㄊ沁x擇最有可能發(fā)現(xiàn)錯(cuò)誤的測(cè)試(一部份功能測(cè)試,一部份覆蓋測(cè)試)。
1.功能測(cè)試
功能測(cè)試一般稱為黑盒子測(cè)試,因?yàn)樵诰帉懝δ軠y(cè)試的測(cè)試?yán)虝r(shí)并沒有涉及實(shí)際的程式碼。換句話說,沒有觸及到‘盒子內(nèi)’。嵌入式系統(tǒng)有輸入和輸出,并在輸入和輸出之間執(zhí)行某些演算法。黑盒子測(cè)試是根據(jù)對(duì)哪些輸入應(yīng)該是可接受的以及這些輸入應(yīng)與輸出有何種關(guān)係的了解來進(jìn)行的。黑盒子測(cè)試完全不了解輸入與輸出之間的演算法是如何實(shí)現(xiàn)的。黑盒子測(cè)試的示例包括:
壓力測(cè)試:有意使輸入通道、記憶體緩衝器、磁碟控制器、記憶體管理系統(tǒng)等過載的測(cè)試
邊界值測(cè)試:表示特定範(fàn)圍內(nèi)的‘邊界’的輸入(例如,對(duì)于整數(shù)輸入而言,是最大和最小整數(shù)以及?1、0、+1);以及應(yīng)使輸出在輸出範(fàn)圍的類似邊界出現(xiàn)跨變的輸入值。
異常測(cè)試:能觸發(fā)故障模式或異常模式的測(cè)試。
錯(cuò)誤推測(cè):根據(jù)以前的軟體測(cè)試經(jīng)驗(yàn)或者從測(cè)試類似程式獲得的經(jīng)驗(yàn)進(jìn)行的測(cè)試。
隨機(jī)測(cè)試:通常,這是效率最低的一種測(cè)試方法,但卻仍然廣泛用于評(píng)估用戶介面程式碼的強(qiáng)韌性。
性能測(cè)試:由于性能預(yù)期是產(chǎn)品要求的一部份,因此性能分析屬于功能測(cè)試的範(fàn)疇。
由于黑盒子測(cè)試僅取決于程式要求及其I/O行為,因此一旦完成功能要求的編寫,即可開發(fā)這類測(cè)試。這使得黑盒子測(cè)試?yán)痰拈_發(fā)可以與余下的系統(tǒng)設(shè)計(jì)同步進(jìn)行。
與所有測(cè)試一樣,功能測(cè)試應(yīng)被設(shè)計(jì)得具有破壞性,也即,要試圖證明程式無法工作。這包括使輸入通道過載、隨意地敲打鍵盤,以及故意地做程式員認(rèn)為會(huì)破壞其程式的所有事情。
作為研發(fā)產(chǎn)品經(jīng)理,這是我的主要測(cè)試方法之一。如果產(chǎn)品在經(jīng)過40個(gè)小時(shí)的極限測(cè)試(abuse testing)后,并沒發(fā)現(xiàn)任何嚴(yán)重或者致命的缺陷,那么就可以發(fā)佈這個(gè)產(chǎn)品了。如果找到了一個(gè)重大的缺陷,那么修正這個(gè)缺陷后,還必須重復(fù)前面的測(cè)試步驟。
2.覆蓋測(cè)試
功能測(cè)試的缺點(diǎn)是其很少執(zhí)行全部程式碼。覆蓋測(cè)試則試圖規(guī)避這個(gè)缺點(diǎn),它採用的方法是(理想地)確保每一條程式碼語句、判定點(diǎn)或者判定路徑都至少被測(cè)試一次。覆蓋測(cè)試還可以顯示已經(jīng)存取的數(shù)據(jù)空間大小。
覆蓋測(cè)試也稱為白盒子測(cè)試或玻璃盒子測(cè)試,這類測(cè)試的設(shè)計(jì)需要全面了解軟體的實(shí)現(xiàn)方式,也就是說,它要‘看到盒子裡面’。白盒子測(cè)試?yán)昧塑汲淌酱a所能提供的方便。
白盒子測(cè)試充分借力了程式員對(duì)程式API、內(nèi)部控制結(jié)構(gòu)的知識(shí),分享了程式員的異常處理能力。由于白盒子測(cè)試取決于具體的實(shí)現(xiàn)決策,因此要到應(yīng)用程式碼完成后,才能動(dòng)手設(shè)計(jì)這類測(cè)試。
從嵌入式系統(tǒng)的角度來看,覆蓋測(cè)試是最重要的測(cè)試,這是因?yàn)橹灰惆盐找言诙啻蟪潭壬蠈?duì)程式碼進(jìn)行了測(cè)試,你就可很好地預(yù)警出現(xiàn)未發(fā)現(xiàn)缺陷的風(fēng)險(xiǎn)。白盒子測(cè)試的示例包括:
語句覆蓋:選擇的測(cè)試案例可以至少將程式中的每一條語句執(zhí)行一次。
判定或分支覆蓋:選擇的測(cè)試?yán)炭梢允姑恳粋€(gè)分支(條件為真和假的路徑)至少執(zhí)行一次。
條件覆蓋:選擇的測(cè)試?yán)炭梢詮?qiáng)制判定中的每一個(gè)條件(項(xiàng))都包含所有可能的邏輯值。
理論上,白盒子測(cè)試可以利用或控制所需的任何對(duì)象來執(zhí)行其測(cè)試。因此,白盒子測(cè)試可能使用JTAG介面強(qiáng)制設(shè)定特定的記憶體值作為測(cè)試的一部份。實(shí)踐上,白盒子測(cè)試可以分析邏輯分析儀報(bào)告的執(zhí)行路徑。
3.灰盒子測(cè)試
由于白盒子測(cè)試可以深入程式碼內(nèi)部,因此與黑盒子測(cè)試相較,這類測(cè)試的維護(hù)成本更高。只要要求和I/O關(guān)係保持穩(wěn)定,黑盒子測(cè)試就會(huì)一直有效;但每次修改程式碼后,可能都需要重新進(jìn)行白盒子測(cè)試。因此成本效益最高的白盒子測(cè)試一般是那些在不深入編程細(xì)節(jié)的情況下利用實(shí)現(xiàn)知識(shí)進(jìn)行的測(cè)試。
較少涉及程式碼細(xì)節(jié)的測(cè)試有時(shí)也稱為灰盒子測(cè)試。當(dāng)與‘錯(cuò)誤推測(cè)’配合使用時(shí),灰盒子測(cè)試非常有效。如果你知道(或者至少猜到)程式碼中的弱點(diǎn)在哪裡,那么你就可以設(shè)計(jì)出對(duì)這些弱點(diǎn)‘施壓’的測(cè)試案例。
因?yàn)檫@些測(cè)試覆蓋了程式碼的特定部份,因此這些測(cè)試是灰盒子測(cè)試;因?yàn)檫@些測(cè)試是根據(jù)可能會(huì)出現(xiàn)哪些錯(cuò)誤的猜測(cè)而選擇的,因此這些測(cè)試是錯(cuò)誤推測(cè)測(cè)試。
在整合新功能與穩(wěn)定的舊程式碼庫時(shí),這種測(cè)試策略非常有用。由于程式碼庫已經(jīng)過全面的測(cè)試,因此將測(cè)試重點(diǎn)集中在新、舊程式碼交集處可以起到事半功倍的效果。
評(píng)論