2008-10-04 169 views
2

將我當前的代碼項目轉換爲TDD,我注意到了一些東西。「代碼覆蓋」與「代碼測試」?

class Foo { 
    public event EventHandler Test; 

    public void SomeFunction() { 
     //snip... 
     Test(this, new EventArgs()); 
    } 
} 

當測試此代碼並依靠代碼覆蓋率工具確定您是否有足夠的測試時,可以看到兩個危險。

  • 您應該測試Test事件是否被觸發。只有代碼覆蓋工具不會告訴你,如果你忘記了這一點。
  • 我會在第二秒內找到另一個。

爲此,我添加了一個事件處理程序,我的啓動功能,使得它看起來是這樣的:

Foo test; 
int eventCount; 

[Startup] public void Init() { 
    test = new Foo(); 
    // snip... 
    eventCount = 0; 
    test.Test += MyHandler; 
} 

void MyHandler(object sender, EventArgs e) { eventCount++; } 

現在,我可以簡單地檢查eventCount看到我的事件被調用多少次,如果它被稱爲。很簡約。只有現在,我們已經通過了一個永遠不會被任何測試捕獲的陰險小錯誤:即,SomeFunction()在嘗試調用它之前不檢查事件是否有任何處理程序。這將導致一個空的解除引用,它將永遠不會被我們的任何測試所捕獲,因爲它們都默認附加了一個事件處理程序。但是,代碼覆蓋工具仍然會報道全面覆蓋。

這只是我手邊的「真實世界的例子」,但即使對代碼有100%的「覆蓋率」,我也會發現有更多的這類錯誤可能會漏過,但這仍然不能解釋到100%測試。在編寫測試時,我們是否應該用這樣一種工具報告覆蓋率?是否還有其他種類的工具可以抓住這些漏洞?

回答

4

我不會說「把它當作一粒鹽」(有很多實用程序代碼覆蓋率的),而是引用自己

TDD和代碼覆蓋不是 靈丹妙藥:

·即使有100%的塊 覆蓋率,仍然會有該選擇哪個 塊執行條件錯誤 。

·即使100%塊 覆蓋率+ 100%弧覆蓋率, 仍然是直線 代碼中的錯誤。

·即使採用100%的塊 覆蓋率+ 100%弧覆蓋範圍+ 100% 執行 無差錯換在-至少一路徑 直線代碼,仍有 將被輸入的數據路徑/循環的方式顯示更多 錯誤。

(從here

雖然可能有一些工具,可以提供改進,我認爲高階位是代碼覆蓋率只是一個整體的測試策略,以確保產品質量的一部分。

+0

好帖子其實,感謝分享。 – 2008-10-04 13:23:56

2

在編寫測試時,我們是否應該用這樣一種工具報道覆蓋率?

絕對。覆蓋工具只會告訴您測試過程中代碼中的哪些比例線實際上是運行。它沒有說明如何徹底清除這些線。一些代碼行只需要測試一次或兩次,但有些需要在各種輸入上進行測試。覆蓋工具無法區分差異。

1

此外,如果測試驅動程序只是對結果的正確性沒有有意義的斷言行使代碼,那麼100%的測試覆蓋率並不意味着太多。

+0

即使有意思的斷言,仍然會出現這樣的情況:您可以執行所有執行線程,完成有意義的測試,但仍然無法完全測試。例如,邊界檢查通常可以在一個條件下完成,但您應該單獨測試欠載和超限。 – 2008-10-04 13:11:52

0

覆蓋範圍僅用於識別尚未經過測試的代碼。它沒有告訴你很多關於已經被覆蓋的代碼。

0

是的,這是「線路覆蓋」和「路徑覆蓋」之間的主要區別。在實踐中,您無法真正測量代碼路徑覆蓋率。像靜態編譯時間檢查,單元測試和靜態分析 - 線覆蓋只是您追求高質量代碼時使用的另一種工具。

4

< 100%的代碼覆蓋率很差,但並不表示100%的代碼覆蓋率是好的。這是一個必要但不充分的條件,應該這樣對待。

另外請注意,有代碼覆蓋和路徑覆蓋之間的差異:

void bar(Foo f) { 
    if (f.isGreen()) accountForGreenness(); 
    if (f.isBig()) accountForBigness(); 
    finishBar(f); 
} 

如果傳遞一個大的,綠富成代碼,測試用例,你會得到100%的代碼覆蓋率。但是,對於所有你知道一個大的,紅色的Foo會使系統崩潰,因爲accountForBigness錯誤地假定某個指針是非空的,只有通過accountForGreenness使其非空。您沒有100%的路徑覆蓋率,因爲您沒有覆蓋跳過accountForGreenness調用的路徑,但沒有覆蓋accountForBigness調用的路徑。

也可以在沒有100%路徑覆蓋的情況下獲得100%分支覆蓋。在上面的代碼中,一次調用一個大的綠色Foo,一個調用一個小紅色的Foo給前者,但仍然沒有發現大紅色的bug。

並不是說這個例子是有史以來最好的OO設計,但很少看到代碼覆蓋暗示路徑覆蓋的代碼。即使它確實意味着在您的代碼中,它並不意味着庫或系統中的所有代碼或所有路徑都被覆蓋,您的程序可能會使用它。原則上,您需要100%覆蓋程序中所有可能的狀態來做到這一點(並因此確保例如在任何情況下您都無法使用無效參數調用,導致圖書館或系統中的錯誤代碼無法獲得),這通常是不可行的。

0

測試是絕對必要的。執行也是必須要考慮的。

如果你以某種沒有在你的測試中的方式實現某些東西,那麼問題就可能發生。

當您測試的數據與將要流經應用程序的數據無關時,也可能發生問題。

所以,代碼覆蓋率是必要的。但不如真人的真實測試。

+0

「當您測試的數據與將要流經應用程序的數據無關時,也可能發生問題。」你會如何編寫測試來爲使用泛型的類實現這一目標? – 2008-10-04 14:25:42