2012-01-06 37 views
1

我的域名涉及隨機確定的選擇,我不確定如何進行單元測試。我應該如何測試隨機選擇?

作爲一個微不足道的例子,假設我想確保myobject.makeChoice()返回的時間爲75%和false。我怎麼能單元測試這個?

  1. 我可以斷言,myobject.getChoiceAPercent()是75,但 似乎微不足道,沒有什麼用處,並不能令人滿意,因爲它沒有測試的實際結果。

  2. 我可以運行myobject.makeChoice() 1000倍,並斷言的時候,它 回報true 70%至80%百分比,或一些統計方法 這樣的,但是卻似乎脆弱的,緩慢的, 不盡人意。

  3. 我可以運行與預定的隨機發生器或 隨機種子一個單元測試和斷言makeChoice()運行5次返回 [true, true, false, true, true],例如,但似乎在 相同斷言隨機(123)== 456也似乎不能令人滿意,因爲我不會測試實際的域名我很感興趣。

似乎隨機選擇可以證明與隨機生成的歸納推理本身而不是單元測試是正確的。那麼隨機生成的內容是不是適合自動化測試,還是有一種我不知道的簡單方法?

[編輯]爲了避免過度的糾紛「真正的隨機」與「僞隨機」等,讓我們假設下面的實現:

public boolean makeChoice() { 
    return this.random.nextDouble() < 0.75; 
} 

我如何單元測試makeChoice回報true的約75%時間?

+0

我很困惑。如果它是隨機的,那麼就沒有辦法讓它保持在75%和25%的水平,而不會根據定義使它變得非隨機... – Andy 2012-01-06 01:38:36

+0

我已經添加了一個澄清問題的實現。 – 2012-01-06 01:56:42

+0

還有一個問題。你的代碼應該返回真正的75%的空間時間,我的意思是在1000次機會中它必須返回750個trues ..或100次機會它返回true .. – 2012-01-06 01:57:11

回答

0

隨機性測試似乎並不隨機。但爲了測試唯一性/衝突,我通常使用散列結構並將隨機值作爲關鍵字插入。重複的密鑰被覆蓋。通過統計唯一密鑰的最終數量與迭代的總次數,可以「測試」算法的唯一性。

+0

我不關心獨特性,我關心隨機性。由於在這個簡單的例子中只有兩個選擇,所以唯一性看起來並不有用。如果我計算重複數據而不是重寫它們,這將與解決方案#2相同:運行它很多次,並聲稱它平均看起來是你期望的。 – 2012-01-06 01:55:03

+0

@TrystanSpangler - 基本上我同意你的解決方案#2。我不確定你的猶豫是什麼,運行一個迭代測試來推斷這兩個選項中每一個的隨機選取次數。 – 2012-01-06 02:00:18

+0

我同意Tim Medora。第二個聽起來像是合乎邏輯的選擇。只需做一定的時間,足以讓您有機會匹配您需要的選擇。在每個選擇中,你可以有一個反對,告訴你有多少真實或錯誤,相比之下,當時是80%比20%等。 – Andy 2012-01-06 02:13:33

0

您寫的代碼與RNG不是分離的。也許你可以這樣寫:

public boolean makeChoice(double randnum) { 
    return randnum < 0.75; 
} 

然後你測試關鍵值來測試實現。

或者你可以初始化隨機對象到一個特定的種子,它給出[0,1)之間的已知隨機數,並測試你期望與那些已知數字發生的事情。

或者你也可以定義一個IRandom,爲Random編寫一個前端,實現接口並在程序中使用它。然後你可以用一個模擬IRandom對它進行測試,依次給出數字0.00,0.01,0.02 ...,0.99,1.00,並計算成功次數。

0

不要測試你的代碼的隨機性,通過傳入或從隨機數存儲中獲取一個值來測試隨機性的結果。

100%單位測試覆蓋率是一個很好的目標,但它是收益遞減規律。你寫過PRNG了嗎?

編輯:還檢查了這個答案,因爲它有一對夫婦的良好的聯繫:How do you test that something is random? Or "random enough'?

0

我第二的「脫鉤」的策略。我喜歡認爲任何依賴於隨機值或時間的東西都應該把它作爲「另一種依賴」的「另一種輸入」來確定性地加以處理。然後你注入一個你要寫或信任的時鐘或RNG。

例如,就你的情況而言,如果「選擇」在80%的時間內是真實的,而不是75%的時間,那麼你的對象是否會有不同的表現?我懷疑你的代碼中有很大一部分只關心選擇是真還是假,而另一個則是做出選擇。

這會打開你如何測試一個隨機生成器的問題,在這種情況下,我想依靠「大數」規則,一些近似值,數學和簡單相信rand()是更好的方法。

0

因爲它是一個隨機的布爾值,寫2個測試(一個用於TRUE,一個用於FALSE)就足夠如果行爲不依賴於過去的「隨機」的結果(這至少是不明確的,對我來說,從問題)。換句話說:如果連續的結果不相互依賴,您可能會測試一個單一的TRUE方案,單個FALSE方案,可能會很好。