天天看點

單元測試極大地提高C/C++應用品質

<b>介紹</b>

如果你沒有執行單元測試,你就會同時失去第一時間改善軟體品質和削減開發時間和成本的機會。這種犧牲當然是令人失望的。在此之前,開發人員一直沒有一種可行的方法來執行單元測試。現在,JAVA開發人員能夠使用ParaSoft的Jtest自動化JAVA單元測試,而C/C++開發人員能夠利用ParaSoft最新的C++Test工具自動化C/C++單元測試。

本文闡述了執行單元測試的方法、優點和難點,然後描述了C++Test任何能夠給C/C++開發人員帶來巨大的好處。

<b>什麼是單元測試?</b>

我們對單元測試的定義是測試應用中最小的單元,如C/C++中的一個類。C/C++單元測試的目的是執行每個類中的每一個方法或函數,檢測所有存在的功能性問題、錯誤和構造弱點。發現這些典型的問題通常涉及到三種測試方法:黑盒測試、白盒測試和回歸測試。黑盒測試通過确定類的公共界面是否依照定義執行,檢查類的功能性;執行這種類型的測試不需要有關實作細節的知識。白盒測試通過确定類在遇到非預期輸入時執行是否正确,檢查所有的類的方法和函數(包括保護和私有成員)的健壯性;執行這種類型的測試需要對類的實作細節的完整知識。回歸測試檢查是否類的修改會在原來正确的代碼中引入新的錯誤。

<b>什麼是單元測試的優點?</b>

單元測試被公認為軟體開發過程中的一個關鍵步驟。單元測試能夠簡化錯誤檢測,在減少開發時間和成本的同時提高軟體品質。

單元測試促進錯誤檢測的第一個方面是使你更接近錯誤。

單獨測試一個類時(與其它對象分離),由于更接近錯誤,找到潛在的錯誤就會變得容易得多。用上述撞球的例子來比喻,就像是台面上隻有壹兩個球時,一杆将一個球擊入指定的袋中。

單元測試促進錯誤檢測的第二個方面是,将你從在問題中艱難跋涉去修正一個簡單錯誤的困境中解救出來。因為錯誤是互相關聯和作用的,在較高的層次上找到和修正一個錯誤,常常會發現另外的問題。當你在較高層次上測試時,原始的錯誤就象是洋蔥的最内層一樣,另外的錯誤就象緊包着内層的其它層:隻有把外層都剝掉才能看到最内層。當你測試每一個類時,錯誤還很少有機會建立在其它錯誤之上,并互相作用引起奇怪的行為。是以在單元級上檢測錯誤會容易的多。

最重要的結果是,更容易的錯誤檢測能夠在改善應用品質的同時大量削減開發時間和成本。首先,由于能夠更容易地找到錯誤,就會減少發現它們的時間和資源。其次,由于你一寫完一個類,就能發現和改正其中的錯誤,你就不需要在以後花費時間重新了解和摸索。最後,最重要的理由是:由于類的互相作用和關聯性,在單元級修改一個類隻會影響到原始的類,而在較高的層次上修改一個類可能會改變多個程式部件的設計和功能性。越遲發現問題,通常就要修改越多的代碼。當修改的代碼量增加時,兩個其它因素也會随之增加:

修改每一個錯誤所需的時間和費用。

在代碼中引入新的錯誤的機會。

一次又一次的研究證明,随着問題被檢測出來的時間的推遲,發現軟體錯誤所需的時間和成本會驚人地增加。請看下面的研究結果:

IBM: 根據IBM的一份内部資料指出,确定軟體錯誤的相對成本是:在設計階段,1.5;編碼前,1;編碼中,1.5;測試前,10;測試中,60;傳遞後,100。[Watts Humphrey]

TRW: 确定錯誤的相對時間:需求分析階段,1;設計階段,3-6;編碼階段,10;開發測試階段,15-40;接受性測試階段,30-70;應用運作中,40-1000。[Boehm]

IBM: 确定錯誤的相對時間:設計評審,1;代碼檢查,20;測試,82。[Remus]

JPL: Bush得出的每個錯誤的平均成本:編碼,US$90-US$120;測試,US$10,000。[Bush]

Freedman and Weinberg: 使用設計評審和代碼檢查手段的項目在測試時發現錯誤的數量會減少10倍,測試成本降低50%-8%,包括評審和檢查的成本。[Freedman]

<b>什麼是單元測試的難點?</b>

基于上述資訊,單元測試看上去就象一劑萬能藥。如果是這樣的話,為什麼每一個C/C++開發人員不馬上對每一個類進行單元測試?就目前可以使用的技術來說,對C/C++的單元測試是一件困難、煩瑣和耗時的事情,沒有很好的工具來自動化這一過程,使得許多C/C++開發人員望而生畏。

執行單元測試的第一步是是目标類變得可測。這需要兩個工作:

設計一個運作目标類的測試驅動程式。

設計樁函數,它們為被測類所引用的任何外部資源傳回值。

建立一個測試驅動,需要建立一個新的類,除了測試原始類以外它不能用于任何其它目的。測試驅動應該具有下列特性:

一個指定設定和清除的标準方式。

一個選擇個别測試和所有有效測試的方法。

一個分析輸出的預期(或非預期)結果的機制。

一個标準的錯誤報告形式。

為了充分而正确地測試類,你需要設計一個能夠完全檢查被測類的測試驅動;若幹次修改和重寫這樣一個測試驅動是免不了的。一旦建立了測試驅動,你必須仔細檢查它不能包含任何錯誤。測試驅動中的一個錯誤會破壞這個測試,但是你無法單獨測試一個類,你也不能測試測試驅動本身。

如果你的類引用任何還沒有準備好或不可通路的外部資源(如外部檔案、資料庫和CORBA對象等),你必須建立相應的樁函數,它們的傳回值類似于這些實際的外部資源應該傳回的值。當建立這些樁函數時,你需要選擇樁函數的傳回值,它們将影響程式的執行路徑...

為了測試類的功能性必須執行任何的路徑,

足夠的路徑能夠提供徹底的測試覆寫性。

下一步是設計和建立合适的測試用例。為了徹底地測試類的結構和功能性,你應該設計兩中類型的測試用例:黑盒和白盒。

黑盒測試用例基于說明和規格文檔。特别地,至少應該為規格文檔的每個入口建立一個測試用例;更好的是這些測試用例能夠測試每個入口的各種邊界條件。還需要為發現的每一個錯誤增加另外的測試用例,以及任何你認為必要的其它測試。

白盒測試用例通過各種不同的輸入充分地執行類的所有方法以發現缺陷。對于手工測試來說這是非常困難的。為了建立有效的白盒測試用例,你必須研究類的内部結構,然後編寫測試用例盡可能完全地覆寫類的所有方法,以及覆寫所有可能引起類崩潰的輸入。要達到較高的測試覆寫性,需要有效的白盒測試用例它們能夠執行相當多數的路徑。例如,一個典型的1萬行的程式,大約有1億條可能的路徑;手工建立能夠執行所有這些路徑的輸入幾乎是不可行的。

在建立這些測試用例以後,你将要執行整個測試用例并分析結果,确定在那裡出現了錯誤、崩潰和薄弱環節。你還需測量這些測試的覆寫性,以确定類被測試的程度以及需要追加的測試用例。

任何時候一個類被修改後,你應該執行回歸測試,保證沒有引入新的錯誤和/或原來的錯誤已經被更正了。回歸測試包括白盒和黑盒測試用例,并且分析結果以确定類的品質是否得到的改善。

<b>C++Test: 一個自動化的單元測試解決方案</b>

ParaSoft認識到了C/C++單元測試内在的的價值和難度,開發了C++Test,一個自動的C/C++單元測試工具,增強了ParaSoft的自動錯誤防止和錯誤檢測産品線。C++Test自動執行所有可能的單元測試過程。特别地,它能夠自動:

建立每個被測類的測試驅動程式。

建立任何必要的樁函數,并允許你定制這些樁函數的傳回值或加入自己的樁函數。

單鍵執行白盒測試的所有步驟。

生成黑盒測試用例的基礎集合。

運作黑盒測試用例。

生成黑盒測試的輸出結果。

執行回歸測試。

跟蹤測試覆寫性。

C++Test能夠測試所有類型的C/C++項目;C++Test甚至能夠支援COM對象,允許你對調用COM對象方法的類和方法執行自動的單元測試。

C++Test還是高度可定制的;例如,你可以改變測試用例的生成參數,過濾一定的檔案、類或方法,在任何層次上(從這個項目到單個方法或測試用例)進行測試。

另外,C++Test很容易與你目前的開發過程合作。C++Test直接安裝在DevStudio環境中,是以你能夠立即測試任何正在開發中的類。隻要在Developer Studio的工具欄上按下<b>Test File</b>或<b>Test Project</b>按鈕,那麼C++Test就會自動在C++Test圖形使用者界面中打開你的檔案,為每個類建立一個測試驅動程式并自動測試每個類。

C++Test實時跟蹤測試覆寫性,然後建立一個綜合測試覆寫性報告。覆寫性視窗圖示化地說明了目前正在被執行的代碼行,已執行過的行和每行的執行次數。是以,它不僅指出了一個代碼行是否被測試過,而且說明了被測試的有多徹底。這些資訊對于确定那些代碼需要追加測試是非常有幫助的。

<b>6. 內建的單步調試</b>

如果你選擇在方法測試時捆綁調試器,C++Test将自動自動激活Microsoft Visual C++調試器,這樣使得你在用C++Test測試任何方法時仍然能夠友善地進行單步調式。

<b>7. 防止錯誤</b>

C++Test能夠自動執行兩種類型的變成标準。其内建的特性允許你自動執行動态的變成标準,如“總是對每個類執行單元測試”和“總是單步調試類”等。另外,假如你使用CodeWizard--ParaSoft的自動化可定制程式設計标準強化工具,C++Test可以自動運作CodeWizard。

<b>8. 運作時錯誤檢測</b>

C++Test還能幫助你執行類一級的運作時錯誤自動檢測。如果你安裝了Insure++,C++Test可以自動運作類和方法通過Insure++,它将檢查下列錯誤:

記憶體引用錯誤/記憶體未初始化

記憶體洩漏

記憶體配置設定錯誤

變量定義沖突

I/O錯誤

指針錯誤

庫調用錯誤

邏輯錯誤

算法錯誤

這意味着你能夠在類開發的第一時間檢測運作時錯誤,而且無需自己做任何運作資料。C++Test自動生成大量而精心設計的測試用例,能夠幫助你更徹底、更友善和更快速地檢測運作時錯誤。

<b>結論</b>

通過執行單元測試,你能夠有效地防止許多錯誤的出現,盡早檢測出已存在的錯誤,并且比其它測試手段和技術更有效。影響C/C++開發人員執行單元測試的主要障礙是需要消耗大量的時間的資源,目前的一些單元測試工具仍然存在着這樣的問題。C++Test的推出克服了這一障礙。C++Test做到了開發人員總是希望卻不敢相信的事情:自動化C/C++單元測試。