How to test random.choice in Python?
Question:
How would you test a function which could lead to a random choice?
For instance:
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
How would you test it?
Answers:
If you want to test it, you can write something like:
lst = [1,2,3,4,5,5]
assert getMaxIndices(lst) in (4,5)
testing that the result is either 4 or 5.
If you want to test that it can be both and is random, run it 1000 times and test that you get 4 and 5 about the same amount of times:
result = 0
for i in range(1000):
result += getMaxIndices(lst)
assert 4.3 <= result/1000 <= 4.7
Since you are not testing the shuffling itself, you should patch shuffle
to return an output set by you in order to have a deterministic test.
In this case it could be something along the lines of:
@patch('random.shuffle', lambda x: x)
def test_get_max_Indices():
max_index = getMaxIndices([4,5,6,7,8])
assert max_index == 4
From the test, you can realise that the return value will simply be dependent on the length of the input list.
You can read more about patch in the docs: https://docs.python.org/dev/library/unittest.mock.html#unittest.mock.patch
Answering this many years later, but I would have some tests for edges cases like an empty list
import pytest
def test_get_max_empty_list():
with pytest.raises(Exception):
getMaxIndices([])
I would also test I got the largest, regardless of what the shuffle does:
def test_get_max_is_largest_for_two_identical_items():
L = [2,2]
max_index = getMaxIndices(L)
assert L[max_index] == max(L)
def test_get_max_is_largest():
L = [2,3,4,5,6]
max_index = getMaxIndices(L)
assert L[max_index] == max(L)
Mocking out the shuffle is fine, and does let you test specifics too, but doesn’t cover the empty edge case.
How would you test a function which could lead to a random choice?
For instance:
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
How would you test it?
If you want to test it, you can write something like:
lst = [1,2,3,4,5,5]
assert getMaxIndices(lst) in (4,5)
testing that the result is either 4 or 5.
If you want to test that it can be both and is random, run it 1000 times and test that you get 4 and 5 about the same amount of times:
result = 0
for i in range(1000):
result += getMaxIndices(lst)
assert 4.3 <= result/1000 <= 4.7
Since you are not testing the shuffling itself, you should patch shuffle
to return an output set by you in order to have a deterministic test.
In this case it could be something along the lines of:
@patch('random.shuffle', lambda x: x)
def test_get_max_Indices():
max_index = getMaxIndices([4,5,6,7,8])
assert max_index == 4
From the test, you can realise that the return value will simply be dependent on the length of the input list.
You can read more about patch in the docs: https://docs.python.org/dev/library/unittest.mock.html#unittest.mock.patch
Answering this many years later, but I would have some tests for edges cases like an empty list
import pytest
def test_get_max_empty_list():
with pytest.raises(Exception):
getMaxIndices([])
I would also test I got the largest, regardless of what the shuffle does:
def test_get_max_is_largest_for_two_identical_items():
L = [2,2]
max_index = getMaxIndices(L)
assert L[max_index] == max(L)
def test_get_max_is_largest():
L = [2,3,4,5,6]
max_index = getMaxIndices(L)
assert L[max_index] == max(L)
Mocking out the shuffle is fine, and does let you test specifics too, but doesn’t cover the empty edge case.