2009-04-23 67 views
7

在單元測試中,我已經習慣於測試應用一些常規值的方法,一些侵犯方法合同的值以及我可以想到的所有邊界情況。在單元測試中使用隨機性和/或迭代?

但它是實踐壞隨機值

  • 測試非常,這是你認爲不應該放棄任何麻煩的範圍內的值,所以每一次的試運行,另一個值傳遞在?作爲一種常規值的廣泛測試?
  • 測試整個範圍,使用迭代?

我有一種感覺,這兩種方法都不是很好。通過範圍測試,我可以想象,這樣做是不切實際的,因爲它需要的時間,但隨機性?

更新:我沒有使用這種技術自己

,只是想知道這件事。如果你可以在需要的時候使其可重現,隨機性可以成爲一個很好的工具,我現在知道了。
最有趣的答覆是從利芬的 '模糊' 提示:

http://en.wikipedia.org/wiki/Fuzz_testing

TX

+3

@彼得:我一直在我的測試用例中使用隨機性。它在SUT中發現了一些錯誤,它在我的測試用例中給了我一些錯誤。測試用例變得更復雜。你需要一種方法來運行你的測試用例,以及它失敗的隨機值等等。總而言之,我重新開始使用隨機性,但並沒有放棄它。就像每種技術一樣,它也有其價值。你應該查看術語「fuzzing」。 – 2009-04-23 10:35:25

+1

Lieven,waarom maak je er geen antwoord van? Ik zou het graag acceptedteren。 – Peter 2009-04-23 10:53:12

+0

@Peter,在dat geval ... – 2009-04-24 16:40:06

回答

3

我一直在測試用例中使用隨機性。它在SUT中發現了一些錯誤,並在我的測試用例中給了我一些錯誤。

請注意,通過使用randomnes,測試用例會變得更加複雜。

  • 你需要一個方法來運行與隨機值(S)未能在
  • 您需要登錄用於每個測試的隨機值你的測試用例。
  • ...

所有的一切,我throthling重新使用隨機性,但不enterly貶。就像每種技術一樣,它也有其價值。

對於你是什麼之後,一個更好的解釋,查找術語fuzzing

2

你在測試?隨機數發生器?或者你的代碼?

如果你的代碼,如果在產生隨機數的代碼中有一個錯誤怎麼辦?

如果您需要重現某個問題,您是否繼續重新開始測試,希望最終能夠使用與發現問題時相同的順序?

如果您決定使用隨機數生成器來生成數據,至少要使用已知的常量值進行種子處理,所以很容易重現。

換句話說,你的「隨機數」只是一個「我真的不關心的數字序列」。

+0

我認爲重生是沒有問題的,我可以在日誌中看到哪個數字觸犯了斷言,不是嗎? – Peter 2009-04-23 10:18:40

+0

斷言的斷言可能不允許你重構有問題的輸入值(例如,當它的assertNotNull或assertTrue對某些派生值) – 2009-04-23 10:29:02

+0

事實上,我猜如果沒有解決這個問題,它可能會排除這種技術,但也許有一個它簡單的解決方案,當然 – Peter 2009-04-23 10:48:59

5

單元測試需要很快。如果他們不是人們不會定期運行它們。有時我做了代碼檢查整個範圍,但@ Ignore'd最後評論它,因爲它使測試過於緩慢。如果我要使用隨機值,我會選擇固定種子的PRNG,這樣每次運行實際上都會檢查相同的數字。

1

只要它能以某種方式告訴你它失敗的隨機值,我不認爲它很糟糕。然而,你幾乎要依靠運氣才能在應用程序中找到問題。

測試整個範圍將確保您覆蓋所有途徑,但當您覆蓋邊緣並且我假設有幾個中間接受的值時,它似乎過度殺傷。

5
  1. 隨機輸入 - 測試不會重複(產生一致的結果每次都運行,因此被認爲是不好的單元測試時,測試不應該改變自己的初衷
  2. 範圍測試/ RowTests。 - 只要他們不會減慢測試套件的運行速度就是好的。每個測試應儘可能以快速運行。 (30秒內完成測試套件的運行頻率比10分鐘更快) - 最好在100ms以內。這就是說每個輸入(測試數據)都應該是「有代表性」的輸入。如果所有輸入值都相同,則測試每個值都不會增加任何值,只是常規數字運算。您只需要從該組值中選擇一位代表。您還需要代表邊界條件和「特殊」值。

更多有關指引或thumbrules - 見'What makes a Good Unit Test?'

這就是說...你提到的技術可能是巨大的,找到代表的投入。所以用它們來尋找scenarioX其中代碼失敗或成功不正確 - 然後爲該場景寫一個可重複的,快速的僅用於測試的單元測試單元測試,然後將其添加到測試套件中。如果您發現這些工具可以繼續幫助您找到更好的測試案例,請堅持使用它們。

迴應OP的澄清:

  • 如果您使用您的隨機在每個測試運行沒有產生相同的種子值(測試輸入),你的測試不是隨機的 - 值可以預定。然而單元測試理想情況下不需要任何輸入/輸出 - 這就是xUnit測試用例具有void TC()簽名的原因。
  • 如果您在每次運行中使用不同的種子值,現在您的測試是隨機的,不可重複。當然,您可以追蹤日誌文件中的特殊種子值,以瞭解失敗的原因(並重現錯誤),但我喜歡我的測試,以便立即讓我知道失敗的原因 - 例如Red TestConversionForEnums()讓我知道Enum轉換代碼在沒有任何檢查的情況下被破壞。

重複 - 意味着每個測試的SUT運行時,它會產生相同的結果(通過/失敗)..不是「?我可以再次重現測試失敗」 (可重複!=可重現)。重申..這種探索性測試可能很好地識別更多的測試用例,但我不會將這添加到我每次在白天進行代碼更改時運行的測試套件中。我建議手動進行探索性測試,找到一些好的(有些人可能會使用虐待性的)測試人員,他們會在您的代碼中使用錘子和鉗子。與隨機輸入生成器相比,您會發現更多的測試用例。

0

我不會主張完全隨機的值,因爲它會給你一種錯誤的安全感。如果你不能通過整個範圍(通常是這種情況),那麼手動選擇子集的效率會更高。這樣,您還必須考慮可能的「奇怪」值,這些值會導致代碼以不同的方式運行(並且不在邊緣附近)。

您可以使用隨機生成器來生成測試值,檢查它們是否代表好樣本,然後使用它們。這是一個好主意,尤其是手動選擇太費時。

我寫了一個信號量驅動程序用於兩個不同芯片的硬件塊時,我確實使用了隨機測試值。在這種情況下,我無法弄清楚如何爲時間選擇有意義的值,所以我隨機化了芯片(獨立地)嘗試訪問塊的頻率。現在回想起來,手動選擇它們仍然會更好,因爲讓測試環境工作的方式使得兩個芯片不符合我的想法。這實際上是隨機值不創建隨機樣本的一個很好的例子。

這個問題是由於這樣一個事實造成的:無論何時其他芯片已經保留了該塊,另一個芯片已經等待,並且對於一個信號量,在另一個芯片釋放它之後就可以訪問。當我繪製芯片需要等待訪問多長時間時,這些值事實上遠不是隨機的。最糟糕的是,當我對兩個隨機值的值範圍相同時,我將它們改爲具有不同的範圍後稍微好一些,但它仍然不是很隨機。我只是在隨機分配訪問之間的等待時間後,纔開始進行隨機測試,並且仔細選擇了四組。

最後,我可能最終會用更多的時間來編寫使用「隨機」值的代碼,而不是先用手挑選有意義的值。

3

你描述的通常被稱爲基於規範的測試,並已通過的框架,如QuickCheck(哈斯克爾),scalacheck(斯卡拉)和Quviq QuickCheck(二郎)來實現。

基於數據的測試工具(如在TestNGDataProvider)可以實現類似的結果。

其基本原理是根據某種規範爲測試對象生成輸入數據,這遠不是「不好的做法」。

1

單元測試的目標是讓您對代碼充滿信心。因此,如果你覺得使用隨機值可以幫助你發現更多的bug,你顯然需要更多的測試來提高你的置信度。

在這種情況下,您可以依靠基於迭代的測試來識別這些問題。 我建議爲循環測試發現的案例創建新的特定測試,然後除去基於迭代的測試;所以他們不會減慢你的測試。

1

我已經使用隨機性調試泄露資源的狀態機的字段問題。我們對代碼進行檢查,運行單元測試並且不能重現泄漏。

我們將整個可能事件空間中的隨機事件送入狀態機單元測試環境。我們在每個事件之後查看不變量,並在違規時停止。

隨機事件最終暴露了一系列產生泄漏的事件。 從第一個錯誤中恢復時,狀態機在發生第二個錯誤時泄露資源。

我們然後能夠重現現場的泄漏。

因此隨機性發現了一個很難找到的問題。有點蠻力,但電腦不介意週末工作。

0

見David孔雀皇對Theory-Based Testing工作。

通常我會避免在單元測試中的隨機性,但理論的東西是有趣的。

0

這裏的'關鍵'點是單元測試。如果種子是恆定的,那麼在迴歸測試中,預期範圍內的一系列隨機值以及好的情況下的邊緣和壞的情況的邊界/邊界是有價值的。

如果可以始終保存前後的輸入/輸出(如果有),則單元測試可以使用預期範圍內的隨機值。