2010-08-09 60 views
29

我想知道在一些單元測試中使用隨機值有什麼缺點。在單元測試中使用隨機值有什麼缺點?


我說的是一個大型系統,有很多服務器和非確定性輸入的大容量。當我說非確定性的時候,我正在討論發送的消息,並且你抓住了你所能做的並盡​​力而爲。 有很多類型的消息,所以輸入可能非常複雜。 我無法想象爲這麼多場景編寫代碼,並且一個簡單的非隨機(確定性)消息的生成器不夠好。 這就是爲什麼我想要一個隨機單元測試或服務器測試,以防萬一發生故障可能會寫日誌。 而我更喜歡單元測試而不是隨機注入器,因爲我希望它可以作爲夜間構建自動化測試的一部分運行。

+1

您能否告訴我們會有什麼好處? – 2010-08-09 16:04:15

+0

在這裏,我編輯了這個問題。 Tnx! – Adibe7 2010-08-09 17:44:31

+1

請注意,如果您輸入一個隨機數發生器的輸入(並且只能在一個線程中訪問它),那麼輸出是可重複的,而不是隨機的。如果擔心的只是一代大數據集的產生,那麼仍然可以使用隨機數生成器,而不需要隨機測試... – Kendrick 2010-08-09 18:08:34

回答

37

缺點

首先,它使測試更加令人費解和稍硬調試,因爲你不能直接看到所有的值被送入(雖然總是有生成測試用例的選擇代碼或數據也是如此)。如果你正在做一些半複雜的邏輯來生成隨機測試數據,那麼這段代碼也有可能存在一個錯誤。測試代碼中的錯誤可能會很痛苦,特別是如果開發人員立即假定錯誤是生產代碼。其次,通常不可能對預期答案進行具體說明。如果你知道基於輸入的答案,那麼你有一個很好的機會,你只是在測試邏輯(考慮它 - 如果輸入是隨機的,你怎麼知道預期的輸出?)結果,你可能必須交易非常具體的斷言(值應該是x)以用於更一般的健全性檢查斷言(值應該在y和z之間)。第三,除非有廣泛的輸入和輸出,否則通常可以在複雜度較低的標準單元測試中使用精心選擇的值來覆蓋相同的範圍。例如。選擇數字-max,(-max + 1),-2,-1,0,1,2,max-1,max。 (或者對算法有意思的東西)。

上升空間

當使用正確的目標做得很好,這些測試可以提供非常有價值的補充測試合格。我已經看到了很多代碼,當被隨機生成的測試輸入敲打時,由於不可預見的邊緣情況而失敗。我有時會添加一個額外的集成測試通行證,以生成大量的測試用例。

額外技巧

如果您的隨機測試失敗,隔離「有趣的」價值,推動它變成一個獨立的單元測試,以確保您可以修正錯誤,它會永遠之前簽入迴歸一個。

+0

如果你打算低估我,請說明原因。我已經使用這些技術來發現和修復錯誤。 – 2010-08-09 17:14:44

+0

對不起,這是一個錯誤。 :) – Adibe7 2010-08-09 21:24:51

+0

感謝回覆:) – 2010-08-09 21:59:10

8

它們是隨機的。

(您測試可能會隨機工作,即使你的代碼被打破了。)

+0

我正在討論對非隨機測試的附加測試 – Adibe7 2010-08-09 15:46:52

+4

您的單元測試旨在證明,如果你的單位工作與否,以可重現的方式。如果你在其他測試中這樣做,你將不需要額外的隨機測試。 您可以使用隨機值使用隨機輸入掃描軟件中未知的安全問題。然而,結果你應該再次寫一個可重複的單元測試。 – relet 2010-08-09 15:51:08

+0

Tnx爲你的答案,你可以再看看現在,我添加了一些更多的補充? – Adibe7 2010-08-09 17:45:27

7

而且,你將不能夠過度繁殖試驗了很多次。單元測試應該與給定的參數完全相同。

+0

這並非總是如此,隨機輸入可以在某些情況下增加代碼覆蓋率。 – 2010-08-09 15:49:32

+3

@NIckLarsen:他們可能*發生*增加代碼覆蓋率,對於一個特定的測試運行......儘管如此,您不能*依賴*。你必須打開盒子才能知道貓是否死了。 – Pete 2010-08-09 15:55:30

+1

@Nick - 那麼你應該提高增加代碼覆蓋率的價值。 – 2010-08-11 10:15:53

3

結果是不可重複的,並且根據您的測試,您可能不知道造成代碼失敗的特定條件(從而導致難以調試)。

+2

這取決於單元測試框架。一個體面的測試框架將輸出什麼值(以及哪個斷言)導致測試失敗。該輸出可用於構建新的硬編碼測試用例。 – 2011-07-16 16:30:47

+0

已更正。謝謝。 – Kendrick 2011-07-18 17:25:39

3

單元測試是100%可重複的幷包含所有邊緣情況要好得多。例如,測試零,負數,正數,數字太大,數字太小等等。如果您想包含除了所有邊緣案例和正常案例之外的隨機值的測試,那麼將會很好。不過,我不確定你會花費多少時間獲得很多好處。擁有所有正常情況和邊緣情況應該處理所有事情。其餘的是「肉汁」。

+0

這個答案很簡單。例如,對於字符串,您可能無法表示整個範圍(長度爲0的字符串,包含無效字符的字符串,非常長的字符串)。一些隨機化最終會發現一些不可預見的邊緣情況。 – 2011-07-16 16:32:13

1

正如其他人所說,它會讓你的測試不可靠,因爲你不知道里面發生了什麼。這意味着它可能適用於某些情況,而不適用於其他情況。

如果您已經對要測試的值範圍有所瞭解,那麼您應該(1)爲範圍中的每個值創建一個不同的測試,或者(2)遍歷該組值並且在每次迭代中做出斷言。一個快速,相當愚蠢的例子...

for($i = 0; $i < 10; $i++) 
    $this->assertEquals($i + 1, Math::addOne($i)); 

你可以做一些類似的字符編碼。例如,循環使用ASCII字符集,並根據您的某個文本處理函數測試所有這些瘋狂字符。

0

您需要記住在驗證期間生成的隨機數。

例子。

Username= "username".rand(); 
Save_in_DB("user",Username); // To save it in DB 
Verify_if_Saved("user",Username); 
0

我認爲隨着等值分區一起使用,生成隨機輸入值可以成爲可靠的測試技術。 這意味着,如果你劃分你的輸入空間,然後從等價類中隨機選擇值,那麼你很好:覆蓋範圍相同(任何一個,包括語句,分支,所有用途等)。 這是根據您的等價劃分過程是正確的假設。 此外,我會建議邊界值分析與等價分區和隨機生成的輸入配對。最後,我還建議考慮要檢測的缺陷類型:一些測試技術解決特定類型的缺陷,這可能很難(並且偶然)由其他技術檢測到。一個例子:死鎖條件。總之,我相信生成隨機值並不是一個壞習慣,特別是在某些系統(例如web應用程序)中,但它只處理現有缺陷的一個子集(像任何其他技術),並且應該知道爲了配合他/她的質量保證過程和適當的一系列活動,

1

隨機化單元測試是使用螺絲刀敲擊指甲。問題不在於螺絲刀不好;問題在於你使用錯誤的工具來完成這項工作。單元測試的重點是當你破壞某些東西時提供即時反饋,所以你可以在那裏修復它。

假設您提交了一個更改,我們將其稱爲BadChange。 BadChange引入了一個錯誤,你的隨機測試有時會被捕獲,有時甚至不會。這一次,測試沒有抓住它。 BadChange已經全部清楚並進入代碼庫。

後來,有人提交了另一個更改,GoodChange。 GoodChange是百分之百的罰款。但是這一次,您的隨機測試會捕獲BadChange引入的錯誤。現在,GoodChange被標記爲一個問題,編寫它的開發人員將圈出圈套,試圖找出爲什麼這個無害的更改會導致問題。

隨機化測試有助於不斷探究整個應用程序的問題,而不是驗證個別更改。它應該生活在一個單獨的套件中,並且運行不應鏈接到代碼更改;即使沒有人做出改變,但隨機測試可能會碰到一些以前缺失的異常缺陷。

0

上行:他們透露你的其他測試有而不是涵蓋了所有的不變量。您是否希望您的CI服務器運行非確定性測試是另一個問題。鑑於我發現https://www.artima.com/shop/scalacheck有多麼令人難以置信的有用,我從現在開始不打算這麼做。假設您正在實施模式匹配算法。你真的瞭解所有不同的角落案例嗎?我不。隨機輸入可能會將其清除。

0

其他Downside尚未提及的是,您的測試可能會間歇性地隨機失敗,尤其是當您隨機生成多個測試變量,因此它們形成複雜且有時難以分辨的依賴關係。見示例here

調試這些是在背面右側疼痛,有時(旁邊)是不可能的。另外,通常很難說出你的測試實際測試了什麼(以及它是否測試了任何東西)。

從歷史上看,我們公司使用多個級別的隨機測試(單元,集成,單一服務測試),這似乎是一個好主意 - 它節省了代碼,空間和時間,允許在一次測試中測試多個場景。當我們的(甚至是過去的歷史和可靠的)測試開始隨機失敗 - 並且解決這些問題需要大量的勞動力時,越來越成爲我們發展的一個棘手問題。

相關問題