Reputation: 327
I have written code like this :
def choice(states):
states = list(states)
rnd = random.random()
for state, p in states:
rnd -= p
if rnd <= 0:
return state
And I need to create some tests :
import unittest
class Tests(unittest.TestCase):
def test_choice(self):
assertEquals(choice(states),something_equl)
How am I supposed to inject my own random number into test? to get deterministic results?
Upvotes: 1
Views: 3673
Reputation: 5099
I would like to improve the response with a full script to better understand and be adaptable to other cases.
import random
from unittest import TestCase, mock
def get_random_words(): # Simple function using choice
l = []
for _ in range(3):
l.append(random.random(0, 10))
return "".join([str(n) for n in l])
class TestRandom(TestCase):
@mock.patch('random.random') # *(1)
def test_get_random_words(self, mock_random):
mock_random.side_effect = [1,7,3,6] # *(2)
result = get_random_words()
self.assertEqual(result, '173', 'Does not generate correct numbers')
*(1) For this example, the function is inside the same file, but in case it is in another file you must change the path of the patch
Ex: @mock.patch('your_package.your_file.your_function.random.random')
*(2) For this case, the get_random_words
function calls random.random
3 times. This is why you must put equal or more items inside mock_random.side_effect
. This is because if it has fewer items it will throw the StopIteration
error.
Upvotes: 0
Reputation: 473873
Mock the random.random()
function, example:
import random
import unittest
import mock
def choice(states):
states = list(states)
rnd = random.random()
for state, p in states:
rnd -= p
if rnd <= 0:
return state
class Tests(unittest.TestCase):
@mock.patch('random.random')
def test_first_state_fires(self, random_call):
random_call.return_value = 1
self.assertEquals(choice([(1, 1)]), 1)
@mock.patch('random.random')
def test_returns_none(self, random_call):
random_call.return_value = 2
self.assertIsNone(choice([(1, 1)]))
Upvotes: 6
Reputation: 1122022
You can use the unittest.mock
library to patch out the random()
function. The library is part of Python 3.3 and up, you can install it separately as mock
for older versions:
try:
from unittest import mock
except ImportError:
import mock
class Tests(unittest.TestCase):
@mock.patch('random.random')
def test_choice(self, mock_random):
mock_random.return_value = 0.42
assertEquals(choice(states),something_equl)
Upvotes: 4