從前面三張圖可以看出,隨著CL值的減小與頻率的提升,性能是都有提升的。DDR2的時(shí)序活動(dòng)空間不大,如果要穩(wěn)定運(yùn)行于CL3時(shí)序,頂級(jí)內(nèi)存也只能降頻到800以下,常用的時(shí)序一般為4-4-4-12和5-5-5-15,而且從測(cè)試數(shù)據(jù)來(lái)看,DDR2內(nèi)存,提升頻率帶來(lái)的性能提升比較明顯,同時(shí),低時(shí)序帶來(lái)的提升也不可忽視。
MEM 333 CL5-5-5-15 4M PI截圖:
EVEREST內(nèi)存測(cè)試截圖:
PCMARK05截圖:
3DMARK05截圖:
MEM 500 CL4-4-4-12 4M PI截圖:
EVEREST截圖:
PCMARK05截圖:
3DMARK05截圖:
應(yīng)用軟件測(cè)試
應(yīng)用軟件測(cè)試,用winrar來(lái)測(cè)試內(nèi)存性能對(duì)實(shí)際日常使用帶來(lái)的影響,壓縮對(duì)象為XPSP2光碟里面的I386目錄,已復(fù)制到硬盤(pán),體積為542M,采用標(biāo)準(zhǔn)壓縮,每測(cè)試一次后刪除壓縮目錄重啟一次。只采用了667CL5和1110CL5兩種此次測(cè)試極端性能模式進(jìn)行對(duì)比。
測(cè)試成績(jī)?yōu)椋寒?dāng)內(nèi)存運(yùn)行667CL5時(shí),壓縮I386目錄用時(shí)3分30秒,而當(dāng)運(yùn)行于1110CL5時(shí),只用了3分鐘,整整快了30秒,相當(dāng)于節(jié)約了1/7的時(shí)間,再一次說(shuō)明了選擇高性能內(nèi)存的必要性。
專(zhuān)業(yè)軟件測(cè)試
專(zhuān)業(yè)軟件測(cè)試:采用的是有代表性的SPECViewperf 10,SPECviewperf 10是圖形工作站專(zhuān)業(yè)顯卡OpenGL測(cè)試程序,可以測(cè)試顯卡在多個(gè)CAD/DCC應(yīng)用程序中的OpenGL性能,包括3ds max、CATIA、EnSight、Maya、Pro/ENGINEER、SolidWorks等,它的成績(jī)可以比較真實(shí)的反映顯卡在這些軟件中的運(yùn)行速度。為了盡量減低CPU的影響,此次測(cè)試CPU更換為默認(rèn)3.16G的E8500,顯卡為9600GT。
SPECViewperf 10測(cè)試項(xiàng)目中,內(nèi)存從333CL5提升到555CL5,各項(xiàng)測(cè)試均有不同程度的提升,以3DSMAX-04提升比例最大,所有的測(cè)試項(xiàng)目都是比較具有代表性的,因此,在專(zhuān)業(yè)軟件應(yīng)用上,提升內(nèi)存性能對(duì)提高工作效率,縮短工作時(shí)間均是有不小幫助的。
柱狀對(duì)比圖:
內(nèi)存333/CL5時(shí)的表現(xiàn):
內(nèi)存500/CL4的表現(xiàn):
總結(jié)
無(wú)論從測(cè)試軟件、普通應(yīng)用軟件還是從專(zhuān)業(yè)軟件的測(cè)試情況來(lái)看,選擇高品質(zhì)內(nèi)存,提升內(nèi)存性能對(duì)于整機(jī)性能的提升具有極大的意義,象國(guó)際知名的G.SKILL、OCZ之類(lèi)的頂級(jí)內(nèi)存品牌,價(jià)格也不是貴得離譜,非常值得選購(gòu)。
1 研究背景
隨著敏捷開(kāi)發(fā)的流行,傳統(tǒng)的軟件測(cè)試也在發(fā)生著翻天覆地的變化。傳統(tǒng)的軟件測(cè)試已不能適應(yīng)當(dāng)前的開(kāi)發(fā)方式,急需新的理論和方法論來(lái)尋求改變,并以此來(lái)推進(jìn)軟件工程的進(jìn)步。本文將關(guān)注與敏捷測(cè)試相關(guān)理論與技術(shù)。
1.1 敏捷技術(shù)方法與分析
我們現(xiàn)在面對(duì)著飛速變化的業(yè)務(wù)和技術(shù)環(huán)境。在這樣一個(gè)環(huán)境中,傳統(tǒng)的軟件開(kāi)發(fā)方法所認(rèn)為需求需要在項(xiàng)目初期分析清楚并且保持穩(wěn)定的想法是行不通的。不能快速持續(xù)的將需求變化融合到軟件中就意味著對(duì)業(yè)務(wù)環(huán)境反映遲鈍,最終導(dǎo)致業(yè)務(wù)上的失敗。同樣,新技術(shù)不斷地涌現(xiàn),也要求軟件產(chǎn)品的代碼時(shí)刻處于一種良好的狀態(tài),能夠適應(yīng)各種調(diào)整。于是,敏捷開(kāi)發(fā)過(guò)程應(yīng)運(yùn)而生。
2001年以Kent Beck,Martin Fowler,Robert C.Martin及Ward Cunningham等為首的一些軟件工程的專(zhuān)家成立了“敏捷聯(lián)盟”(Agile Alliance),并提出了著名的敏捷宣言,即敏捷過(guò)程的價(jià)值觀:
? 人和交互重于過(guò)程和工具。
? 可以工作的軟件重于求全責(zé)備的文檔。
? 客戶(hù)合作重于合同談判。
? 隨時(shí)應(yīng)對(duì)變化重于循規(guī)蹈矩。
這些價(jià)值觀是專(zhuān)家們?cè)谇笸娈惖幕A(chǔ)上對(duì)敏捷技術(shù)的最基本的總結(jié),也是他們?cè)诿艚菁夹g(shù)方面達(dá)成的最大共識(shí),其反映的是兩個(gè)更深層的特點(diǎn):
1) 敏捷型方法是“適應(yīng)性”而非“預(yù)見(jiàn)性”
工程方法試圖對(duì)一個(gè)軟件開(kāi)發(fā)項(xiàng)目在很長(zhǎng)的時(shí)間跨度內(nèi)做出詳細(xì)的計(jì)劃, 然后依計(jì)劃進(jìn)行開(kāi)發(fā)。這類(lèi)方法在一般情況下工作良好,但(需求、環(huán)境等) 有變化時(shí)就不太靈了。因此它們本質(zhì)上是拒絕變化的。而敏捷型方法則歡迎變化。其實(shí),它們的目的就是成為適應(yīng)變化的過(guò)程,甚至能允許改變自身來(lái)適應(yīng)變化。
2) 敏捷型方法是“面向人”的,而非“面向過(guò)程”的
工程型方法的目標(biāo)是定義一個(gè)過(guò)程,不管是誰(shuí)用都工作。而敏捷型方法 則認(rèn)為沒(méi)有任何過(guò)程能代替開(kāi)發(fā)組的技能,過(guò)程起的作用是對(duì)開(kāi)發(fā)組的 工作提供支持。
敏捷聯(lián)盟還以這4個(gè)價(jià)值觀為原則,提出了敏捷過(guò)程的12條指導(dǎo)原則,以期能更好的指導(dǎo)人們了解敏捷過(guò)程。
敏捷開(kāi)發(fā)過(guò)程,指的就是一種與傳統(tǒng)的瀑布模型開(kāi)發(fā)和CMM(Capability Maturity Model,軟件開(kāi)發(fā)的能力成熟度模型)所追求的嚴(yán)謹(jǐn)?shù)奈臋n制度截然相反的開(kāi)發(fā)過(guò)程。這一開(kāi)發(fā)過(guò)程注重開(kāi)發(fā)團(tuán)隊(duì)和成員之間的關(guān)系而不是以開(kāi)發(fā)的進(jìn)程和使用的工具為重點(diǎn),注重所開(kāi)發(fā)的軟件產(chǎn)品而不是追求廣泛的文檔編制,注重開(kāi)發(fā)過(guò)程中與客戶(hù)的協(xié)同工作而不是以簽訂合同的談判為工作的核心,注重在開(kāi)發(fā)過(guò)程中隨時(shí)調(diào)整計(jì)劃而不是同意完全遵循某一開(kāi)發(fā)計(jì)劃,以實(shí)現(xiàn)所謂開(kāi)發(fā)過(guò)程的“敏捷”。
1.2 敏捷測(cè)試及其研究現(xiàn)狀
敏捷方法的發(fā)展,打破了傳統(tǒng)的瀑布開(kāi)發(fā)模型,改變了整個(gè)軟件開(kāi)發(fā)過(guò)程中的角色和定位。由于在敏捷開(kāi)發(fā)運(yùn)動(dòng)的初期,主要依靠開(kāi)發(fā)人員來(lái)進(jìn)行推動(dòng)。很多測(cè)試人員不了解敏捷方法,仍然習(xí)慣了按照傳統(tǒng)的瀑布模式進(jìn)行軟件測(cè)試,即按照V模型所指導(dǎo)的步驟進(jìn)行測(cè)試,保證軟件與需求、設(shè)計(jì)的相符合,但這樣很容易形成了一種測(cè)試思維的定勢(shì)。當(dāng)“用戶(hù)需求不明確”、“需求變化較快”時(shí),沿用傳統(tǒng)測(cè)試方法的測(cè)試人員將變的無(wú)所適從。
目前比較流行的敏捷測(cè)試方法有測(cè)試驅(qū)動(dòng)開(kāi)發(fā)和相關(guān)環(huán)境驅(qū)動(dòng)測(cè)試等。還有很多國(guó)外知名專(zhuān)家按照“敏捷”的原理為軟件測(cè)試開(kāi)發(fā)了相應(yīng)的測(cè)試框架,其中最著名的就是Kent Beck等提出的xUnit系列單元測(cè)試框架和Ward Cunningham等提出的Framework for Integrated Test(FIT)集成測(cè)試框架。xUnit系列提出的比較早,目前已有一套完善的測(cè)試工具和方法論來(lái)支持了,適用于各種語(yǔ)言的單元測(cè)試。FIT框架是當(dāng)前國(guó)內(nèi)外的研究重點(diǎn),很多知名的測(cè)試專(zhuān)家如Lisa Crispin等都在如何使用FIT進(jìn)行有效的軟件測(cè)試方面得出了很多的研究成果。
1.3 基于接口參數(shù)的測(cè)試用例自動(dòng)生成算法
在軟件測(cè)試工作中,由于輸入、輸出空間,特別是輸入空間的無(wú)限性,使得無(wú)法對(duì)軟件進(jìn)行全面的測(cè)試。因此,如何從大量的輸入數(shù)據(jù)中挑選適量的具有代表性、典型性的數(shù)據(jù),特別是怎樣用較少的測(cè)試用例對(duì)軟件進(jìn)行較全面的測(cè)試是測(cè)試人員面臨的一大難題。
測(cè)試用例的選擇無(wú)論是對(duì)黑箱測(cè)試還是對(duì)白箱測(cè)試都起著關(guān)鍵的作用,決定著軟件測(cè)試的質(zhì)量和效果。所謂測(cè)試用例選擇就是指從所有的可用測(cè)試用例中選出少量典型的測(cè)試用例,以達(dá)到對(duì)測(cè)試域的最大限度覆蓋。多年來(lái),許多研究者對(duì)之進(jìn)行了廣泛而深入的研究,并取得了許多研究成果。常用的基于接接口參數(shù)的黑箱測(cè)試用例選擇方法是對(duì)系統(tǒng)每個(gè)接口參數(shù)采用邊際值分析法和等價(jià)類(lèi)劃分法等選取一組典型的值,然后在這些取值組合中隨機(jī)選取一組測(cè)試用例,或者使用一些啟發(fā)式方法從中進(jìn)行篩選。但這些方法的缺點(diǎn)是帶有主觀傾向性,不具有普遍性。
2 基于敏捷測(cè)試的相關(guān)技術(shù)討論
2.1 FIT框架及應(yīng)用
在敏捷開(kāi)發(fā)過(guò)程中,軟件測(cè)試是至關(guān)重要的,尤其是在最為流行的敏捷開(kāi)發(fā)過(guò)程:極限編程(XP)中顯的更為突出。誠(chéng)然,所有的過(guò)程都提到測(cè)試,但一般都不怎么強(qiáng)調(diào)。可是XP將測(cè)試作為開(kāi)發(fā)的基礎(chǔ),要求每個(gè)程序員寫(xiě)一段源碼時(shí)都得寫(xiě)相應(yīng)的測(cè)試碼。這些測(cè)試片段不斷地積累并被整合到系統(tǒng)中。這樣的過(guò)程會(huì)產(chǎn)生一個(gè)高度可靠的建造平臺(tái),為進(jìn)一步開(kāi)發(fā)提供了良好的基礎(chǔ)。
但是,即使是單元測(cè)試工具JUnit也存在一些缺點(diǎn):比如JUnit里要進(jìn)行數(shù)據(jù)填充,但是數(shù)據(jù)經(jīng)常改變,使維護(hù)工作變成了可怕的噩夢(mèng),測(cè)試不同的組合,需要不同的數(shù)據(jù),這也許會(huì)使測(cè)試工作變得日益復(fù)雜。而目前的集成測(cè)試又缺乏有效的方法論,不能自動(dòng)化,測(cè)試的質(zhì)量比較依賴(lài)測(cè)試人員的水平。
Framework for Integrated Test(簡(jiǎn)稱(chēng)FIT)就是一個(gè)用于增強(qiáng)交流和協(xié)作的工具。FIT創(chuàng)建了一個(gè)在客戶(hù)和程序員之間的反饋循環(huán)。FIT讓客戶(hù)和測(cè)試人員可以使用諸如Microsoft Office之類(lèi)的工具來(lái)給出程序應(yīng)當(dāng)如何表現(xiàn)的例子——而無(wú)需成為直接編碼的程序員。FIT自動(dòng)針對(duì)實(shí)際的程序檢測(cè)那些例子,這樣就在業(yè)務(wù)世界和軟件工程世界之間建立了一個(gè)簡(jiǎn)單而且有效的橋梁。
FIT給予了客戶(hù)和程序員一個(gè)關(guān)于軟件的精確交流的方法。客戶(hù)所給的具體的例子讓程序員能深刻理解將要構(gòu)建的產(chǎn)品。程序員的對(duì)于裝置的工作和軟件可以讓客戶(hù)給出不同的例子進(jìn)行試驗(yàn)來(lái)獲取對(duì)于軟件如何真正工作更深入的了解。這樣通過(guò)一起工作,整個(gè)團(tuán)隊(duì)可以學(xué)會(huì)更多關(guān)于產(chǎn)品的內(nèi)容并產(chǎn)生更好的結(jié)果。
2.2 測(cè)試用例自動(dòng)生成技術(shù)
正交試驗(yàn)設(shè)計(jì)起源于科學(xué)試驗(yàn),它由田口玄一博士在1949年創(chuàng)立,并于60年代初從日本傳人中國(guó)。它應(yīng)用依據(jù)Galois理論導(dǎo)出的正交表,從大量試驗(yàn)條件中挑選出適量的、有代表性的條件來(lái)合理地安排試驗(yàn)。運(yùn)用這種方法安排的試驗(yàn)具有“均勻分散、整齊可比”的特點(diǎn)。“均勻分散”性使試驗(yàn)點(diǎn)均衡地分布在試驗(yàn)范圍內(nèi),讓每個(gè)試驗(yàn)點(diǎn)有充分的代表性;“整齊可比”性使試驗(yàn)結(jié)果的分析十分方便,可以估計(jì)各因素對(duì)指標(biāo)的影響,找出影響事物變化的主要因素。
但正交試驗(yàn)設(shè)計(jì)仍然存在著一些有待解決的弊端:比如正交表難以構(gòu)造,因素、水平過(guò)多時(shí)測(cè)試用例數(shù)目還是過(guò)多等。所以一些專(zhuān)家又提出一種基于對(duì)接口參數(shù)進(jìn)行組合覆蓋的黑箱測(cè)試用例自動(dòng)生成算法模型,據(jù)此來(lái)得到一個(gè)對(duì)所有接口參數(shù)進(jìn)行兩兩組合覆蓋的測(cè)試用例表。這種方法有著類(lèi)似正交試驗(yàn)設(shè)計(jì)的特點(diǎn),實(shí)際上,在特定情況下,這種算法模型得出的測(cè)試用例表就是正交表。
3 技術(shù)實(shí)現(xiàn)的考慮
3.1 基于FIT框架對(duì)軟件進(jìn)行集成測(cè)試
使用基于FIT框架的開(kāi)源FIT工具來(lái)實(shí)現(xiàn)真正的測(cè)試先行開(kāi)發(fā)過(guò)程,并讓客戶(hù)、需求提報(bào)工程師、開(kāi)發(fā)人員、以及測(cè)試人員進(jìn)行協(xié)同工作,達(dá)到需求更精準(zhǔn)、減少需求更改、測(cè)試數(shù)據(jù)與JUnit單元測(cè)試代碼分離的目的,讓這一切更簡(jiǎn)潔、更易于維護(hù)。
將根據(jù)以下步驟進(jìn)行研究:
1) 使用FIT框架進(jìn)行實(shí)際項(xiàng)目測(cè)試的實(shí)踐,從中提煉出一套使用FIT框架進(jìn)行集成測(cè)試的通用方法。
2) 通過(guò)實(shí)踐,對(duì)FIT框架進(jìn)行合理的改進(jìn)和拓展,結(jié)合JUnit單元測(cè)試,現(xiàn)實(shí)單元測(cè)試和集成測(cè)試的無(wú)縫連接,達(dá)到提高軟件質(zhì)量的效果。
3) 在理論研究和實(shí)踐的基礎(chǔ)上,規(guī)約出適用于單元測(cè)試和集成測(cè)試的通用方法。
3.2 整合測(cè)試用例的自動(dòng)生成技術(shù)至FIT
按照敏捷過(guò)程中“簡(jiǎn)單”原則,本課題將編寫(xiě)一個(gè)輔助接口測(cè)試的工具,用來(lái)自動(dòng)產(chǎn)生少而有效的測(cè)試用例,以達(dá)到對(duì)測(cè)試域的最大限度覆蓋。通過(guò)該工具產(chǎn)生的測(cè)試用例表,能符合FIT框架的要求,并可被FIT所執(zhí)行而得到HTML形式的可視化的測(cè)試結(jié)果。通過(guò)這種方式,大大增加了測(cè)試的自動(dòng)化。
為了實(shí)現(xiàn)該目標(biāo),將按照以下步驟進(jìn)行研究:
1) 查看“正交試驗(yàn)設(shè)計(jì)方法”的原理及其資料,了解測(cè)試用例生成的規(guī)則。
2) 查閱兩兩覆蓋測(cè)試用例生成的相關(guān)算法,并根據(jù)算法用程序?qū)崿F(xiàn),進(jìn)行實(shí)踐研究。
3) 根據(jù)實(shí)踐研究,對(duì)兩兩覆蓋測(cè)試用例進(jìn)行改進(jìn),以期能更高效的實(shí)現(xiàn)測(cè)試用例的生成。
4) 修改依據(jù)改進(jìn)后的算法實(shí)現(xiàn)的測(cè)試工具,使其輸入輸出符合FIT框架的要求。在此基礎(chǔ)上,把此工具集成到FIT框架中。
4 小結(jié)
本文討論了當(dāng)前軟件測(cè)試中的兩大重要研究領(lǐng)域:敏捷測(cè)試方法和測(cè)試用例的選擇與生成技術(shù)。進(jìn)一步的工作是,根據(jù)“敏捷”的集成測(cè)試框架FIT需要人工構(gòu)造表格形式的數(shù)據(jù)作為輸入的前提,深入研究如何自動(dòng)生成FIT需要的表格數(shù)據(jù)?再對(duì)FIT進(jìn)行擴(kuò)展,為FIT嵌入測(cè)試用例表格自動(dòng)生成功能。其中測(cè)試用例集的生成將依據(jù)各參數(shù)兩兩覆蓋的原則,以求達(dá)到對(duì)測(cè)試域的最大限度覆蓋
軟件開(kāi)發(fā)和使用的歷史已經(jīng)留給了我們很多由于軟件缺陷而導(dǎo)致的巨大財(cái)力、物力損失的經(jīng)驗(yàn)教訓(xùn)。這些經(jīng)驗(yàn)教訓(xùn)迫使我們這些測(cè)試工程師們必須采取強(qiáng)有力的檢測(cè)措施來(lái)檢測(cè)未發(fā)現(xiàn)的隱藏的軟件缺陷。 生產(chǎn)軟件的最終目的是為了滿(mǎn)足客戶(hù)需求,我們以客戶(hù)需求作為評(píng)判軟件質(zhì)量的標(biāo)準(zhǔn),認(rèn)為軟件缺陷( Software Bug )的具體含義包括下面幾個(gè)因素: ? 軟件未達(dá)到客戶(hù)需求的功能和性能; ? 軟件超出客戶(hù)需求的范圍; ? 軟件出現(xiàn)客戶(hù)需求不能容忍的錯(cuò)誤; ? 軟件的使用未能符合客戶(hù)的習(xí)慣和工作環(huán)境。 考慮到設(shè)計(jì)等方面的因素,我們還可以認(rèn)為軟件缺陷還可以包括軟件設(shè)計(jì)不符合規(guī)范,未能在特定的條件(資金、范圍等)達(dá)到最佳等。可惜的是,我們中的很多人更傾向于把軟件缺陷看成運(yùn)行時(shí)出現(xiàn)問(wèn)題上來(lái),認(rèn)為軟件測(cè)試僅限于程序提交之后。 在目前的國(guó)內(nèi)環(huán)境下,我們幾乎看不到完整準(zhǔn)確的客戶(hù)需求說(shuō)明書(shū),加以客戶(hù)的需求時(shí)時(shí)在變,追求完美的測(cè)試變得不太可能。因此作為一個(gè)優(yōu)異的測(cè)試人員,追求軟件質(zhì)量的完美固然是我們的宗旨,但是明確軟件測(cè)試現(xiàn)實(shí)與理想的差距,在軟件測(cè)試中學(xué)會(huì)取舍和讓步,對(duì)軟件測(cè)試是有百益而無(wú)一弊的。 下面是一些軟件測(cè)試的常識(shí),對(duì)這些常識(shí)的理解和運(yùn)用將有助于我們?cè)谶M(jìn)行軟件測(cè)試時(shí)能夠更好的把握軟件測(cè)試的尺度。 ? 測(cè)試是不完全的(測(cè)試不完全) 很顯然,由于軟件需求的不完整性、軟件邏輯路徑的組合性、輸入數(shù)據(jù)的大量性及結(jié)果多樣性等因素,哪怕是一個(gè)極其簡(jiǎn)單的程序,要想窮盡所有邏輯路徑,所有輸入數(shù)據(jù)和驗(yàn)證所有結(jié)果是非常困難的一件事情。我們舉一個(gè)簡(jiǎn)單的例子,比如說(shuō)求兩個(gè)整數(shù)的最大公約數(shù)。其輸入信息為兩個(gè)正整數(shù)。但是如果我們將整個(gè)正整數(shù)域的數(shù)字進(jìn)行一番測(cè)試的話(huà),從其數(shù)目的無(wú)限性我們便可證明是這樣的測(cè)試在實(shí)際生活中是行不通的,即便某一天我們能夠窮盡該程序,只怕我們乃至我們的子孫都早已作古了。為此作為軟件測(cè)試,我們一般采用等價(jià)類(lèi)和邊界值分析等措施來(lái)進(jìn)行實(shí)際的軟件測(cè)試,尋找最小用例集合成為我們精簡(jiǎn)測(cè)試復(fù)雜性的一條必經(jīng)之道。 ? 測(cè)試具有免疫性(軟件缺陷免疫性) 軟件缺陷與病毒一樣具有可怕的 “ 免疫性 ” ,測(cè)試人員對(duì)其采用的測(cè)試越多,其免疫能力就越強(qiáng),尋找更多軟件缺陷就更加困難。由數(shù)學(xué)上的概率論我們可以推出這一結(jié)論。假設(shè)一個(gè) 50000 行的程序中有 500 個(gè)軟件缺陷并且這些軟件錯(cuò)誤分布時(shí)均勻的,則每 100 行可以找到一個(gè)軟件缺陷。我們假設(shè)測(cè)試人員用某種方法花在查找軟件缺陷的精力為 X 小時(shí) /100 行。照此推算,軟件存在 500 個(gè)缺陷時(shí),我們查找一個(gè)軟件缺陷需要 X 小時(shí),當(dāng)軟件只存在 5 個(gè)錯(cuò)誤時(shí),我們每查找一個(gè)軟件缺陷需要 100X 小時(shí)。實(shí)踐證明,實(shí)際的測(cè)試過(guò)程比上面的假設(shè)更為苛刻,為此我們必須更換不同的測(cè)試方式和測(cè)試數(shù)據(jù)。該例子還說(shuō)明了在軟件測(cè)試中采用單一的方法不能高效和完全的針對(duì)所有軟件缺陷,因此軟件測(cè)試應(yīng)該盡可能的多采用多種途徑進(jìn)行測(cè)試。 ? 測(cè)試是 “ 泛型概念 ” (全程測(cè)試) 我一直反對(duì)軟件測(cè)試僅存在于程序完成之后。如果單純的只將程序設(shè)計(jì)階段后的階段稱(chēng)之為軟件測(cè)試的話(huà),需求階段和設(shè)計(jì)階段的缺陷產(chǎn)生的放大效應(yīng)會(huì)加大。這非常不利于保證軟件質(zhì)量。需求缺陷、設(shè)計(jì)缺陷也是軟件缺陷,記住 “ 軟件缺陷具有生育能力 ” 。軟件測(cè)試應(yīng)該跨越整個(gè)軟件開(kāi)發(fā)流程。需求驗(yàn)證(自檢)和設(shè)計(jì)驗(yàn)證(自檢)也可以算作軟件測(cè)試(建議稱(chēng)為:需求測(cè)試和設(shè)計(jì)測(cè)試)的一種。軟件測(cè)試應(yīng)該是一個(gè)泛型概念,涵蓋整個(gè)軟件生命周期,這樣才能確保周期的每個(gè)階段禁得起考驗(yàn)。同時(shí)測(cè)試本身也需要有第三者進(jìn)行評(píng)估(信息系統(tǒng)審計(jì)和軟件工程監(jiān)理),即測(cè)試本身也應(yīng)當(dāng)被測(cè)試,從而確保測(cè)試自身的可靠性和高效性。否則自身不正,難以服人。 另外還需指出的是軟件測(cè)試是提高軟件產(chǎn)品質(zhì)量的必要條件而非充分條件,軟件測(cè)試是提高產(chǎn)品質(zhì)量最直接、最快捷的手段,但決不是一個(gè)根本手段。 ? 80-20 原則 80% 的軟件缺陷常常生存在軟件 20% 的空間里。這個(gè)原則告訴我們,如果你想使軟件測(cè)試有效地話(huà),記住常常光臨其高危多發(fā) “ 地段 ” 。在那里發(fā)現(xiàn)軟件缺陷的可能性會(huì)大的多。這一原則對(duì)于軟件測(cè)試人員提高測(cè)試效率及缺陷發(fā)現(xiàn)率有著重大的意義。聰明的測(cè)試人員會(huì)根據(jù)這個(gè)原則很快找出較多的缺陷而愚蠢的測(cè)試人員卻仍在漫無(wú)目的地到處搜尋。 80-20 原則的另外一種情況是,我們?cè)谙到y(tǒng)分析、系統(tǒng)設(shè)計(jì)、系統(tǒng)實(shí)現(xiàn)階段的復(fù)審,測(cè)試工作中能夠發(fā)現(xiàn)和避免 80% 的軟件缺陷,此后的系統(tǒng)測(cè)試能夠幫助我們找出剩余缺陷中的 80% ,最后的 5% 的軟件缺陷可能只有在系統(tǒng)交付使用后用戶(hù)經(jīng)過(guò)大范圍、長(zhǎng)時(shí)間使用后才會(huì)曝露出來(lái)。因?yàn)檐浖䴗y(cè)試只能夠保證盡可能多地發(fā)現(xiàn)軟件缺陷,卻無(wú)法保證能夠發(fā)現(xiàn)所有的軟件缺陷。 80-20 原則還能反映到軟件測(cè)試的自動(dòng)化方面上來(lái),實(shí)踐證明 80% 的軟件缺陷可以借助人工測(cè)試而發(fā)現(xiàn), 20% 的軟件缺陷可以借助自動(dòng)化測(cè)試能夠得以發(fā)現(xiàn)。由于這二者間具有交叉的部分,因此尚有 5% 左右的軟件缺陷需要通過(guò)其他方式進(jìn)行發(fā)現(xiàn)和修正。 ? 為效益而測(cè)試 為什么我們要實(shí)施軟件測(cè)試,是為了提高項(xiàng)目的質(zhì)量效益最終以提高項(xiàng)目的總體效益。為此我們不難得出我們?cè)趯?shí)施軟件測(cè)試應(yīng)該掌握的度。軟件測(cè)試應(yīng)該在軟件測(cè)試成本和軟件質(zhì)量效益兩者間找到一個(gè)平衡點(diǎn)。這個(gè)平衡點(diǎn)就是我們?cè)趯?shí)施軟件測(cè)試時(shí)應(yīng)該遵守的度。單方面的追求都必然損害軟件測(cè)試存在的價(jià)值和意義。一般說(shuō)來(lái),在軟件測(cè)試中我們應(yīng)該盡量地保持軟件測(cè)試簡(jiǎn)單性,切勿將軟件測(cè)試過(guò)度復(fù)雜化,拿物理學(xué)家愛(ài)因斯坦的話(huà)說(shuō)就是: Keep it simple but not too simple 。 ? 缺陷的必然性 軟件測(cè)試中,由于錯(cuò)誤的關(guān)聯(lián)性,并不是所有的軟件缺陷都能夠得以修復(fù)。某些軟件缺陷雖然能夠得以修復(fù)但在修復(fù)的過(guò)程中我們會(huì)難免引入新的軟件缺陷。很多軟件缺陷之間是相互矛盾的,一個(gè)矛盾的消失必然會(huì)引發(fā)另外一個(gè)矛盾的產(chǎn)生。比如我們?cè)诮鉀Q通用性的缺陷后往往會(huì)帶來(lái)執(zhí)行效率上的缺陷。更何況在缺陷的修復(fù)過(guò)程中,我們常常還會(huì)受時(shí)間、成本等方面的限制因此無(wú)法有效、完整地修復(fù)所有的軟件缺陷。因此評(píng)估軟件缺陷的重要度、影響范圍,選擇一個(gè)折中的方案或是從非軟件的因素(比如提升硬件性能)考慮軟件缺陷成為我們?cè)诿鎸?duì)軟件缺陷時(shí)一個(gè)必須直面的事實(shí)。 ? 軟件測(cè)試必須有預(yù)期結(jié)果 沒(méi)有預(yù)期結(jié)果的測(cè)試是不可理喻的。軟件缺陷是經(jīng)過(guò)對(duì)比而得出來(lái)的。這正如沒(méi)有標(biāo)準(zhǔn)無(wú)法進(jìn)行度量一樣。如果我們事先不知道或是無(wú)法肯定預(yù)期的結(jié)果,我們必然無(wú)法了解測(cè)試正確性。這很容易然人感覺(jué)如盲人摸象一般,不少測(cè)試人員常常憑借自身的感覺(jué)去評(píng)判軟件缺陷的發(fā)生,其結(jié)果往往是把似是而非的東西作為正確的結(jié)果來(lái)判斷,因此常常出現(xiàn)誤測(cè)的現(xiàn)象。 ? 軟件測(cè)試的意義 - 事后分析 軟件測(cè)試的目的單單是發(fā)現(xiàn)缺陷這么簡(jiǎn)單嗎?如果是 “ 是 ” 的話(huà),我敢保證,類(lèi)似的軟件缺陷在下一次新項(xiàng)目的軟件測(cè)試中還會(huì)發(fā)生。古語(yǔ)說(shuō)得好, “ 不知道歷史的人必然會(huì)重蹈覆轍 ” 。沒(méi)有對(duì)軟件測(cè)試結(jié)果進(jìn)行認(rèn)真的分析,我們就無(wú)法了解缺陷發(fā)生的原因和應(yīng)對(duì)措施,結(jié)果是我們不得不耗費(fèi)的大量的人力和物力來(lái)再次查找軟件缺陷。很可惜,目前大多測(cè)試團(tuán)隊(duì)都沒(méi)有意識(shí)到這一點(diǎn),測(cè)試報(bào)告中缺乏測(cè)試結(jié)果分析這一環(huán)節(jié)。 結(jié)論: 軟件測(cè)試是一個(gè)需要 “ 自覺(jué) ” 的過(guò)程,作為一個(gè)測(cè)試人員,遇事沉著,把持尺度,從根本上應(yīng)對(duì)軟件測(cè)試有著正確的認(rèn)識(shí),希望本文對(duì)讀者對(duì)軟件測(cè)試的認(rèn)識(shí)有所幫助 |
以下內(nèi)容含腳本,或可能導(dǎo)致頁(yè)面不正常的代碼 |
---|
說(shuō)明:上面顯示的是代碼內(nèi)容。您可以先檢查過(guò)代碼沒(méi)問(wèn)題,或修改之后再運(yùn)行. |
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
10.jpg
基于模式的靜態(tài)代碼分析、運(yùn)行時(shí)內(nèi)存監(jiān)測(cè)、單元測(cè)試以及數(shù)據(jù)流分析等軟件驗(yàn)證技術(shù)是查找嵌入式C語(yǔ)言程序/軟件缺陷行之有效的方法。上述技術(shù)中的每一種都能查找出某一類(lèi)特定的錯(cuò)誤。即便如此,如果用戶(hù)僅采用上述技術(shù)中的一種或者幾種來(lái)進(jìn)行驗(yàn)證,這樣的驗(yàn)證方法很有可能會(huì)漏過(guò)對(duì)程序中的一些缺陷的檢查。解決此類(lèi)問(wèn)題的一種安全和有效的策略就是同時(shí)使用上述軟件驗(yàn)證中的所有互補(bǔ)技術(shù)。這樣就能建立起一個(gè)牢固的框架來(lái)幫助用戶(hù)檢查出可能會(huì)避開(kāi)某種特定技術(shù)的缺陷。與此同時(shí),用戶(hù)也自然地建立起一個(gè)能檢測(cè)出關(guān)鍵并且難以查找的功能性錯(cuò)誤的環(huán)境。
本文將詳盡闡述基于模式的靜態(tài)代碼分析、運(yùn)行時(shí)內(nèi)存錯(cuò)誤檢測(cè)、單元測(cè)試以及數(shù)據(jù)流分析等自動(dòng)化技術(shù)共同使用時(shí)是如何查找出嵌入式C語(yǔ)言程序/軟件中的缺陷的。本文中將以Parasoft C++test為例來(lái)演示上述各項(xiàng)技術(shù)。C++teST是一個(gè)經(jīng)廣泛的最佳實(shí)踐證明能提升軟件開(kāi)發(fā)團(tuán)隊(duì)開(kāi)發(fā)效率以及軟件質(zhì)量的自動(dòng)化集成解決方案。
當(dāng)讀者在閱讀本文以及任何時(shí)候思考查找到的缺陷時(shí),關(guān)注文中的截圖是很重要的。自動(dòng)化檢測(cè)例如內(nèi)存崩潰和死鎖的缺陷,毫無(wú)疑問(wèn)對(duì)任何開(kāi)發(fā)團(tuán)隊(duì)都是一項(xiàng)必不可少的任務(wù)。盡管如此,最致命的缺陷卻是功能性錯(cuò)誤,這往往是難以自動(dòng)發(fā)現(xiàn)的。在本文的結(jié)論部分我們將簡(jiǎn)要地討論一下查找這些缺陷的技術(shù)。
情景簡(jiǎn)介
為了給出一個(gè)具體的示例,我們將就一個(gè)我們最近遇到的案例來(lái)介紹以及演示我們所推薦的缺陷查找策略:一個(gè)運(yùn)行在ARM 板上的簡(jiǎn)單傳感器應(yīng)用程序。
假設(shè)我們已經(jīng)創(chuàng)建了該應(yīng)用系統(tǒng),但是當(dāng)我們將程序上載到系統(tǒng)目標(biāo)板上并試圖運(yùn)行該程序時(shí),我們沒(méi)有在LCD屏上看到所預(yù)期的輸出。
我們尚不明確系統(tǒng)不能正常工作的原因,因此我們?cè)O(shè)法對(duì)系統(tǒng)進(jìn)行調(diào)試,但是在目標(biāo)板上進(jìn)行調(diào)試是一件耗時(shí)而且煩人的事。因?yàn)槲覀儾坏貌皇謩?dòng)分析調(diào)試器的結(jié)果并試圖人工判斷出問(wèn)題的真正原因。或者我們使用一些被證實(shí)能自動(dòng)定位出錯(cuò)誤的工具或技術(shù)來(lái)幫助我們減輕負(fù)擔(dān)。
從這一點(diǎn)而言,我們要么期待使用調(diào)試器來(lái)調(diào)試程序能夠帶來(lái)好運(yùn),要么我們嘗試使用一種自動(dòng)化的測(cè)試策略來(lái)查找代碼中所存在的錯(cuò)誤。如果自動(dòng)化技術(shù)仍然沒(méi)有幫助我們查找到錯(cuò)誤,那么我們不得不回到使用調(diào)試器作為最后的辦法。
基于模式的靜態(tài)代碼分析
這里,我們假設(shè)僅在絕對(duì)必要的情況下才使用調(diào)試器進(jìn)行調(diào)試,因此我們從運(yùn)行基于模式的靜態(tài)代碼分析開(kāi)始。它將查找到如下圖所示的問(wèn)題:
這是違反了 MISRA 的一個(gè)規(guī)則,此違規(guī)說(shuō)明該處的賦值運(yùn)算符存在一些可疑情況。的確,編程者此處的本意是使用比較運(yùn)算符而不是賦值運(yùn)算符。因此我們將此處檢測(cè)到的沖突修改掉,并重新運(yùn)行程序。
我們發(fā)現(xiàn)有了一些改善:一些輸出被顯示在了LCD屏上了。但是,由于一次訪問(wèn)違規(guī),程序崩潰掉了。因此我們需要再次地做出選擇。我們是應(yīng)該使用調(diào)試器還是繼續(xù)使用自動(dòng)化的錯(cuò)誤檢測(cè)技術(shù)。由于經(jīng)驗(yàn)告訴我們自動(dòng)化錯(cuò)誤檢測(cè)技術(shù)能非常高效地檢查出我們當(dāng)前程序所遇到的內(nèi)存崩潰這類(lèi)問(wèn)題,因此我們決定使用運(yùn)行時(shí)內(nèi)存監(jiān)測(cè)來(lái)查找問(wèn)題。
整個(gè)程序的運(yùn)行時(shí)內(nèi)存監(jiān)測(cè)
為了進(jìn)行運(yùn)行時(shí)內(nèi)存監(jiān)測(cè),我們使用 C++test 來(lái)插裝應(yīng)用程序。這樣的插裝是輕量級(jí)的,所以經(jīng)過(guò)插裝后的程序適合在目標(biāo)板上運(yùn)行。當(dāng)我們把程序上載到目標(biāo)板上并運(yùn)行經(jīng)過(guò)插裝的程序后,我們將結(jié)果下載到PC上,如下的錯(cuò)誤將被報(bào)告出來(lái):
該結(jié)果指出在第48行代碼處產(chǎn)生了一次讀取數(shù)組越界的錯(cuò)誤。顯然,msgIndex變量的值肯定超過(guò)了數(shù)組的范圍。如果我們隨著堆棧追蹤上一級(jí)的原因,我們將發(fā)現(xiàn)此處的打印信息所指示的值的確超出了數(shù)組的范圍(因?yàn)樵谡{(diào)用printMessage()函數(shù)前我們給出了一個(gè)錯(cuò)誤的條件)。我們可以刪除掉這個(gè)不必要的條件(value <= 20)以修改這個(gè)錯(cuò)誤。
void handleSensorValue(int value)
{
initialize();
int index = -1;
if (value >= 0 && value <= 10) {
index = VALUE_LOW;
} else if ((value > 10) && (value <= 20)) {
index = VALUE_HIGH;
}
printMessage(index, value);
}
然后我們重新運(yùn)行程序,將不會(huì)再報(bào)告任何內(nèi)存錯(cuò)誤。當(dāng)我們把程序上載到目標(biāo)板上時(shí),它似乎如我們預(yù)期那么在工作了。盡管如此,我們?nèi)匀挥幸恍⿹?dān)心。
我們僅查找到我們所執(zhí)行的代碼路徑中的一個(gè)內(nèi)存寫(xiě)溢出實(shí)例,我們憑什么能夠斷定我們尚未執(zhí)行到的代碼就不會(huì)有內(nèi)存寫(xiě)溢出錯(cuò)誤了呢?如果我們檢查覆蓋率分析,我們就會(huì)發(fā)現(xiàn)reportSensorFailure()這個(gè)函數(shù)從未被執(zhí)行到。我們有必要對(duì)這個(gè)函數(shù)進(jìn)行測(cè)試,但是具體如何進(jìn)行呢?建立一個(gè)調(diào)用該函數(shù)的單元測(cè)試用例就是一個(gè)不錯(cuò)的辦法。
在單元測(cè)試中使用運(yùn)行時(shí)內(nèi)存監(jiān)測(cè):我們使用C++test的測(cè)試用例向?qū)?lái)創(chuàng)建一個(gè)測(cè)試用例的框架,并向其中添加一些測(cè)試代碼。然后運(yùn)行該測(cè)試用例——以檢查上面提到的未經(jīng)測(cè)試的函數(shù),同時(shí)打開(kāi)運(yùn)行時(shí)內(nèi)存監(jiān)測(cè)功能。使用C++teST,全過(guò)程大約只需要數(shù)秒鐘。結(jié)果標(biāo)明該函數(shù)已經(jīng)被覆蓋到了,但同時(shí)也查找到了新的錯(cuò)誤:
我們的測(cè)試用例查找到了更多的內(nèi)存相關(guān)錯(cuò)誤。很顯然,當(dāng)失敗處理函數(shù)被調(diào)用時(shí),我們的內(nèi)存初始化存在問(wèn)題(空指針)。通過(guò)更進(jìn)一步的分析,我們發(fā)現(xiàn)在reportSensorValue()函數(shù)中存在函數(shù)調(diào)用順序錯(cuò)誤。finalize()函數(shù)先于printMessage()函數(shù)被調(diào)用,但是finalize()函數(shù)中釋放了printMessage()函數(shù)需要使用的內(nèi)存。
void finalize()
{
if (messages) {
free(messages[0]);
free(messages[1]);
free(messages[2]);
}
free(messages);
}
將函數(shù)調(diào)用順序進(jìn)行修改后,我們重新運(yùn)行程序。
這樣我們就解決了上面報(bào)告中的第一個(gè)錯(cuò)誤。現(xiàn)在我們?cè)賮?lái)分析報(bào)告中的第二個(gè)錯(cuò)誤:即打印信息中的AccessViolatiONException。產(chǎn)生這個(gè)錯(cuò)誤的原因是相應(yīng)的消息列表未經(jīng)初始化。為了解決該問(wèn)題,我們?cè)诖蛴≡撔畔⑶罢{(diào)用一次initialize()函數(shù)來(lái)對(duì)其進(jìn)行初始化。經(jīng)修改后的函數(shù)如下所示:
void reportSensorFailure()
{
initialize();
printMessage(ERROR, 0);
finalize();
}
當(dāng)我們?cè)俅芜\(yùn)行該測(cè)試用例時(shí),僅有一個(gè)任務(wù)被報(bào)告出來(lái):未經(jīng)驗(yàn)證的單元測(cè)試用例(an unvalidated unit test case),這其實(shí)并不算一條錯(cuò)誤。我們只需對(duì)輸出進(jìn)行一下驗(yàn)證,以將該測(cè)試用例轉(zhuǎn)換為回歸測(cè)試。通過(guò)創(chuàng)建合適的斷言,C++test會(huì)自動(dòng)為我們完成這些步驟。
接下來(lái)我們?cè)俅芜\(yùn)行整個(gè)程序。覆蓋率分析告訴我們幾乎整個(gè)程序都已經(jīng)被覆蓋到了,并且沒(méi)有發(fā)現(xiàn)任何內(nèi)存錯(cuò)誤。
這樣就結(jié)束了嗎?其實(shí)不然。雖然我們運(yùn)行了整個(gè)程序并為未覆蓋到的函數(shù)創(chuàng)建了單元測(cè)試用例,但還是有一些路徑是沒(méi)有被覆蓋到的。我們?nèi)匀豢梢岳^續(xù)創(chuàng)建單元測(cè)試用例,但是若指望通過(guò)這樣的方法來(lái)覆蓋程序中的所有路徑將耗費(fèi)相當(dāng)長(zhǎng)的時(shí)間。或者我們使用另外的方法,使用數(shù)據(jù)流分析來(lái)對(duì)這些路徑進(jìn)行模擬。
數(shù)據(jù)流分析
我們使用C++test的BugDetective來(lái)進(jìn)行數(shù)據(jù)流分析,BugDetective能模擬系統(tǒng)中的不同路徑并檢查這些路徑中是否存在潛在的問(wèn)題。進(jìn)行數(shù)據(jù)流分析后,我們得到如下結(jié)果:
仔細(xì)分析報(bào)告的結(jié)果,我們發(fā)現(xiàn)程序中存在一條未被覆蓋到的潛在路徑可能會(huì)造成在finalize()函數(shù)中出現(xiàn)兩次free的操作。在程序中,reportSensorValue()函數(shù)調(diào)用了finalize()函數(shù),然后finalize()函數(shù)調(diào)用了free()。同時(shí),finalize()函數(shù)還會(huì)被mainLoop()函數(shù)調(diào)用。我們可以修改finalize()函數(shù)以使其更加智能化,從而修復(fù)這個(gè)問(wèn)題,修改后的代碼如下:
void finalize()
{
if (messages) {
free(messages[0]);
free(messages[1]);
free(messages[2]);
free(messages);
messages = 0;
}
}
現(xiàn)在我們?cè)俅芜\(yùn)行數(shù)據(jù)流分析,得到的結(jié)果將只有兩個(gè)問(wèn)題:
這里我們可能使用了-1作為索引來(lái)訪問(wèn)了數(shù)組。這是由于整型變量index被設(shè)置的初始值為-1,并且存在一條可能通過(guò)if語(yǔ)句的路徑在未將該整型變量正確的進(jìn)行初始化之前便調(diào)用了printMessage()函數(shù)。運(yùn)行時(shí)分析未檢查到這樣的一條路徑,并且該路徑很有可能在真實(shí)世界中永遠(yuǎn)不可能被執(zhí)行到。這就是靜態(tài)數(shù)據(jù)流分析相對(duì)于運(yùn)真實(shí)運(yùn)行時(shí)內(nèi)存監(jiān)測(cè)最主要的不足:數(shù)據(jù)流分析能檢查出潛在的路徑,這些路徑可能包含在程序?qū)嶋H執(zhí)行過(guò)程中不會(huì)執(zhí)行到或不存在的路徑。盡管如此,為了做到有備無(wú)患,我們刪除了上述的不必要的條件(value>=0)以修改這個(gè)潛在的錯(cuò)誤。
void handleSensorValue(int value)
{
initialize();
int index = -1;
if (value <= 10) {
index = VALUE_LOW;
} else {
index = VALUE_HIGH;
}
printMessage(index, value);
}
相同地,我們也對(duì)最后一個(gè)報(bào)告的錯(cuò)誤進(jìn)行相應(yīng)的處理。現(xiàn)在我們?cè)俅芜\(yùn)行數(shù)據(jù)流分析,將不會(huì)再有錯(cuò)誤被報(bào)告出來(lái)。
為了確保程序運(yùn)行一切正常,我們重新運(yùn)行整個(gè)分析過(guò)程。首先,我們開(kāi)啟運(yùn)行時(shí)內(nèi)存監(jiān)測(cè)并運(yùn)行應(yīng)用程序,一切表現(xiàn)正常。然后我們開(kāi)啟內(nèi)存監(jiān)測(cè)并運(yùn)行單元測(cè)試,一個(gè)任務(wù)被報(bào)告出來(lái):
我們的單元測(cè)試檢測(cè)到reportSensorFailure()函數(shù)的行為已經(jīng)發(fā)生了改變。這是由于我們已經(jīng)對(duì)finalize()函數(shù)進(jìn)行了修改——為了糾正之前報(bào)告的一個(gè)問(wèn)題所做的修改。此處報(bào)告的任務(wù)是為了讓我們注意此修改,并提示我們應(yīng)該對(duì)測(cè)試用例進(jìn)行相應(yīng)的審查,并且確定是否應(yīng)該對(duì)代碼或者測(cè)試用例進(jìn)行相應(yīng)的修改,以表示這種新的行為實(shí)際上是我們所預(yù)期的行為。在檢查完代碼之后,我們發(fā)現(xiàn)后者(修改)是正確的并且應(yīng)該更新斷言的正確條件。
/* CPPtest_TEST_CASE_BEGIN test_reportSensorFailure */
/* CPPTEST_TEST_CASE_CONTEXT void reportSensorFailure(void) */
void sensor_tests_test_reportSensorFailure()
{
/* Pre-condition initialization */
/* Initializing global variable messages */
{
messages = 0 ;
}
{
/* Tested function call */
reportSensorFailure();
/* Post-condition check */
CPPTEST_ASSERT(0 == ( messages ));
}
}
/* CPPTEST_TEST_CASE_END test_reportSensorFailure */
作為最終的確認(rèn),我們需要獨(dú)立地運(yùn)行整個(gè)程序——在IDE中關(guān)閉掉運(yùn)行時(shí)內(nèi)存監(jiān)測(cè)來(lái)對(duì)程序進(jìn)行構(gòu)建。結(jié)果顯示一切如我們所預(yù)期一樣運(yùn)行。
總結(jié)
作為全文的結(jié)尾,讓我們一起對(duì)上述各個(gè)步驟進(jìn)行一個(gè)鳥(niǎo)瞰式的總結(jié)。
首先,我們開(kāi)發(fā)的程序并未如我么所預(yù)期那樣運(yùn)行,我們不得不在兩種解決方法中選擇一種來(lái)查找程序中的錯(cuò)誤:通過(guò)運(yùn)行調(diào)試器或者使用自動(dòng)錯(cuò)誤檢測(cè)技術(shù)。
如果我們使用調(diào)試器運(yùn)行代碼來(lái)查找錯(cuò)誤,我們將會(huì)看到一些很奇怪的現(xiàn)象:程序中的一些變量總是被賦予了相同的值。基于這種現(xiàn)象我們不得不通過(guò)排除法來(lái)查找問(wèn)題的原因——即在應(yīng)該使用比較運(yùn)算符的地方我們錯(cuò)誤地使用了賦值運(yùn)算符。而靜態(tài)代碼分析則能為我們自動(dòng)地檢查出該邏輯錯(cuò)誤。運(yùn)行時(shí)內(nèi)存分析是不可能檢查出這種錯(cuò)誤的,因?yàn)檫@種錯(cuò)誤與內(nèi)存無(wú)關(guān)。數(shù)據(jù)流分析也很有可能找不到這類(lèi)錯(cuò)誤因?yàn)閿?shù)據(jù)流分析僅僅是通過(guò)這些路徑而不會(huì)驗(yàn)證這些條件的正確性。
當(dāng)我們解決了這個(gè)問(wèn)題后,程序可以運(yùn)行了,但是仍然還有內(nèi)存相關(guān)的問(wèn)題。內(nèi)存相關(guān)的問(wèn)題是很難被調(diào)試器發(fā)現(xiàn)的;當(dāng)用戶(hù)使用調(diào)試器調(diào)試程序時(shí),用戶(hù)并不知道內(nèi)存的實(shí)際大小。但是自動(dòng)錯(cuò)誤檢查工具能夠做到這點(diǎn)。因此,為了查找這些內(nèi)存問(wèn)題,我們將整個(gè)程序進(jìn)行插裝,并使用運(yùn)行時(shí)內(nèi)存分析工具來(lái)運(yùn)行程序。這樣我們就能知道到底是那一片內(nèi)存發(fā)生了寫(xiě)溢出錯(cuò)誤。
盡管如此,在審查覆蓋率分析結(jié)果的時(shí)候,我們注意到在目標(biāo)板上測(cè)試的時(shí)候,并不是全部代碼都被覆蓋到了。通過(guò)自動(dòng)化的工具得到這樣的覆蓋率信息是簡(jiǎn)單的,因?yàn)楣ぞ邥?huì)自動(dòng)地
跟蹤覆蓋率,但是,如果我們是通過(guò)調(diào)試器,就不得不判斷哪一部分程序經(jīng)過(guò)了驗(yàn)證。而這通常只能依靠我們?nèi)斯び涗浀姆绞絹?lái)實(shí)現(xiàn)。
當(dāng)工具提醒我們一些代碼未被覆蓋到時(shí),我們決定改變單元測(cè)試來(lái)額外地增加我們測(cè)試執(zhí)行的覆蓋率。這就揭示了程序中另外一些問(wèn)題。在目標(biāo)系統(tǒng)的正常測(cè)試中,覆蓋所有函數(shù)也許是不可能完成的任務(wù),因?yàn)槠渲幸恍┖瘮?shù)可能是硬件的失敗處理函數(shù)或僅在某些小概率的特定情況下才會(huì)被調(diào)用的函數(shù)。而對(duì)這些函數(shù)的測(cè)試對(duì)于一些注重安全性的程序而言又是至關(guān)重要的。試想在飛機(jī)上用來(lái)處理速度傳感器問(wèn)題的程序中存在著代碼錯(cuò)誤:我們會(huì)有系統(tǒng)崩潰的危險(xiǎn),而不是導(dǎo)致某個(gè)設(shè)備為非工作狀態(tài)。因此,通過(guò)創(chuàng)建單元測(cè)試用例來(lái)覆蓋這類(lèi)型的執(zhí)行路徑往往是對(duì)其進(jìn)行有效測(cè)試的唯一方法。
接下來(lái),我們修復(fù)了工具檢查到的所有問(wèn)題,同時(shí)通過(guò)驗(yàn)證相應(yīng)的結(jié)果創(chuàng)建了一個(gè)回歸測(cè)試用例(作為報(bào)告的任務(wù)之一引導(dǎo)我們完成)。然后我們運(yùn)行數(shù)據(jù)流分析來(lái)覆蓋在目標(biāo)系統(tǒng)上即便使用單元測(cè)試也未執(zhí)行到的路徑。在此之前,我們幾乎已經(jīng)達(dá)到了100%的代碼行覆蓋率,但是我們的路徑覆蓋率卻未達(dá)到這個(gè)水平。BugDetective幫我們發(fā)現(xiàn)了這些方面的一些潛在問(wèn)題。這些問(wèn)題可能并沒(méi)有實(shí)際發(fā)生或者有可能永遠(yuǎn)不會(huì)發(fā)生。也許在實(shí)際運(yùn)行時(shí),這些問(wèn)題僅僅會(huì)在當(dāng)其條件滿(mǎn)足的情況下才會(huì)出現(xiàn),并且在現(xiàn)實(shí)生活中,這些條件可能永遠(yuǎn)不可能滿(mǎn)足。盡管如此,我們不能保證隨著代碼的升級(jí),應(yīng)用程序不會(huì)執(zhí)行到這些路徑。
安全起見(jiàn),我們?nèi)匀恍薷牧怂鶊?bào)告的問(wèn)題以排除任何可能影響它的實(shí)際應(yīng)用執(zhí)行的風(fēng)險(xiǎn)。在修改代碼的同時(shí),我們同時(shí)也引入了回歸測(cè)試,當(dāng)我們?cè)俅芜\(yùn)行單元測(cè)試時(shí)立即被檢測(cè)到。在所有的自動(dòng)化錯(cuò)誤檢測(cè)方法中,回歸測(cè)試是唯一能夠幫助我們檢查到代碼是否發(fā)生了功能性的改變的方法,并且能驗(yàn)證出對(duì)代碼進(jìn)行的修改是否引入了功能性的錯(cuò)誤以及不可預(yù)知的副作用。最后,我們修改了回歸測(cè)試套件,并重新測(cè)試代碼,發(fā)現(xiàn)一切運(yùn)行正常。
正如讀者所見(jiàn),我們使用的一切測(cè)試方法——基于模式的靜態(tài)代碼分析、內(nèi)存分析、單元測(cè)試、數(shù)據(jù)流分析以及回歸測(cè)試——并不是相互競(jìng)爭(zhēng)的關(guān)系,恰好相反,它們是一種互補(bǔ)的關(guān)系。將上述工具結(jié)合使用,它們就是一套具有強(qiáng)大作用的工具集,并為嵌入式C語(yǔ)言程序/軟件提供一個(gè)無(wú)可比擬的自動(dòng)化錯(cuò)誤檢測(cè)解決方案。
總而言之,通過(guò)自動(dòng)地查找很多關(guān)于內(nèi)存和其它編碼的缺陷,我們成功地讓程序運(yùn)行起來(lái)了。盡管如此,值得注意的是,最危險(xiǎn)的缺陷卻是實(shí)際的功能性錯(cuò)誤:例如程序并未如所指定的要求運(yùn)行。而不幸的是,這些錯(cuò)誤往往是非常難以被發(fā)現(xiàn)的。
查找這類(lèi)缺陷的最好的一個(gè)方式就是通過(guò)同行代碼審查來(lái)實(shí)現(xiàn)。即另指派至少一人來(lái)檢查代碼并且審查代碼與需求內(nèi)容的一致性,這樣用戶(hù)就能對(duì)實(shí)際程序是否會(huì)如預(yù)期那樣運(yùn)行有一個(gè)很好的*估。
另外一個(gè)十分有用的策略是圍繞代碼創(chuàng)建一個(gè)回歸測(cè)試套件,這能幫助用戶(hù)快捷地驗(yàn)證代碼與規(guī)范的一致性。在本文所描述的示例情景中,單元測(cè)試被用來(lái)強(qiáng)制執(zhí)行應(yīng)用程序級(jí)的運(yùn)行時(shí)內(nèi)存監(jiān)測(cè)所未覆蓋到的代碼:它能覆蓋到當(dāng)前程序的功能性,在此之后,我們對(duì)代碼做了一些修改,它能提醒我們代碼出現(xiàn)的相應(yīng)的功能性問(wèn)題。事實(shí)上,這種單元測(cè)試用例應(yīng)該被更早地創(chuàng)建起來(lái):理想情況下,當(dāng)用戶(hù)在實(shí)現(xiàn)程序的功能時(shí)就應(yīng)該被創(chuàng)建起來(lái)。這樣,用戶(hù)就能得到更高的覆蓋率并同時(shí)構(gòu)建起一個(gè)更強(qiáng)壯的“安全網(wǎng)”來(lái)捕捉關(guān)鍵的功能性改變。
Parasoft的C++test能幫助用戶(hù)完成這兩個(gè)任務(wù):從自動(dòng)化到管理同行代碼審查流程,以及幫助團(tuán)隊(duì)創(chuàng)建,持續(xù)地運(yùn)行并維護(hù)一個(gè)高效的回歸測(cè)試套件。
關(guān)于Parasoft C++test
Parasoft C++test是一個(gè)經(jīng)廣泛的最佳實(shí)踐證明能提升軟件開(kāi)發(fā)團(tuán)隊(duì)開(kāi)發(fā)效率以及軟件質(zhì)量的自動(dòng)化集成解決方案。C++test能進(jìn)行諸如編碼策略增強(qiáng)、靜態(tài)代碼分析、運(yùn)行時(shí)內(nèi)存監(jiān)測(cè)、自動(dòng)同行代碼審查以及單元和組件測(cè)試,從而為軟件開(kāi)發(fā)團(tuán)隊(duì)提供一種更加實(shí)用的方法來(lái)確保其C以及C++程序能如所預(yù)期那樣工作。C++test可以用于在通用開(kāi)發(fā)IDE下的桌面平臺(tái)中,以及在回歸測(cè)試時(shí)通過(guò)命令行以批處理模式的方式運(yùn)行。同時(shí),C++test還集成了Parasoft的報(bào)告系統(tǒng),該系統(tǒng)能提供具有細(xì)分能力的基于Web 的儀表板,這使得開(kāi)發(fā)團(tuán)隊(duì)根據(jù)C++test的測(cè)試結(jié)果和其他的一些關(guān)鍵進(jìn)程指標(biāo)來(lái)更加方便地跟蹤項(xiàng)目的狀態(tài)和趨勢(shì)。
通過(guò)在宿主機(jī)上進(jìn)行大量的測(cè)試以及在目標(biāo)系統(tǒng)中進(jìn)行的平滑的驗(yàn)證,C++test能夠幫助軟件開(kāi)發(fā)團(tuán)隊(duì)減少花在嵌入式系統(tǒng)開(kāi)發(fā)中的時(shí)間、精力以及成本。隨著代碼在宿主機(jī)上的構(gòu)建,C++test的自動(dòng)化框架使得開(kāi)發(fā)者能在目標(biāo)硬件系統(tǒng)尚未準(zhǔn)備好的情況下就開(kāi)始測(cè)試以提升代碼質(zhì)量。這大大地縮短了花在目標(biāo)系統(tǒng)上測(cè)試的時(shí)間。早期在宿主機(jī)上構(gòu)建的測(cè)試套件可以被重用來(lái)在仿真器或真實(shí)的目標(biāo)板上驗(yàn)證程序的功能性。
]]>