2017-03-14 61 views
2

你將如何測試一個可能導致隨機選擇的函數?如何在Python中測試random.choice?

例如:

from random import shuffle 

def getMaxIndices(lst): 
    ''' 
    :lst: list of int 

    Return indices of max value. If max value appears more than once, 
    we chose one of its indices randomly. 
    ''' 
    index_lst = [(i, j) for i, j in enumerate(lst)] 
    shuffle(index_lst) 
    index_lst.sort(key=lambda x: x[1]) 
    max_index = index_lst.pop()[0] 
    return max_index 

你會如何測試它?

+1

你要測試什麼?隨機生成器是真正的隨機數,還是你的邏輯對所有可能的隨機輸入都正確?你真的需要第一個嗎?如果是後者:只需將處理輸入值的處理與隨機數生成相分離,只需向處理程序和單元測試處理程序注入一個數字即可。 – k0pernikus

+0

我完全同意你的第一點,我不應該寫這個函數,只是文檔字符串。我不確定要理解你的第二點(其實,我確信我沒有),你能否更明確一些? – Gaut

+0

我的第二點是關心不關心源值的隨機性。假設您想通過「美好的一天!」隨機迎接客戶!和「怎麼了!」。然後你需要的是一個接受整數的函數,例如'0'表示「美好的一天」,'1'表示''什麼「。這個函數不需要知道輸入是隨機的,只需要接受一定範圍的輸入來輸出合適的結果。而且你可以進行單元測試。 – k0pernikus

回答

2

既然你是不是測試洗牌本身,你應該修補shuffle給換貨政...由您設定的輸出,以便進行確定性測試。

在這種情況下,它可能是沿着線的東西:

@patch('random.shuffle', lambda x: x) 
def test_get_max_Indices(): 
    max_index = getMaxIndices([4,5,6,7,8]) 
    assert max_index == 4 

從測試的,可以實現的返回值將僅僅是依賴於輸入列表的長度。

您可以在文檔閱讀更多關於補丁:https://docs.python.org/dev/library/unittest.mock.html#unittest.mock.patch

0

如果你想測試它,你可以寫類似:

lst = [1,2,3,4,5,5] 
assert getMaxIndices(lst) in (4,5) 

測試的結果是4或5.

如果你想測試,它可以同時並隨機的,運行了1000次,測試你得到4,5大約相同數量的時間:

result = 0 
for i in range(1000): 
    result += getMaxIndices(lst) 
assert 4.3 <= result/1000 <= 4.7 
+0

有人看到相同的錯誤,並編輯了這個問題。該測試的問題在於,如果我的函數每次返回4,它都會起作用。 – Gaut

+0

編輯測試隨機性 –

+1

隨機性是如此奇怪,以至於一次測試運行始終返回'4'將是完全有效的。所以我認爲它不應該將測試標記爲失敗。 (我確實記得寫了一個硬幣翻轉程序,只是爲了看看我多次重啓以便連續得到10,100或1000個磁頭,10個磁頭相當容易,在數百萬次重試中有1000個磁區,但它確實發生了。)或者只是看這個:https://www.youtube.com/watch?v=rwvIGNXY21Y – k0pernikus

相關問題