Python 在测试中注入随机数
我写了这样的代码:
def choice(states):
states = list(states)
rnd = random.random()
for state, p in states:
rnd -= p
if rnd <= 0:
return state
现在我需要创建一些测试:
import unittest
class Tests(unittest.TestCase):
def test_choice(self):
assertEquals(choice(states),something_equl)
我该怎么把我自己的随机数字放进测试里,以便得到可重复的结果呢?
3 个回答
0
我想通过一个完整的脚本来改善这个回应,这样可以更好地理解并适应其他情况。
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) 在这个例子中,函数是在同一个文件里的,但如果它在另一个文件中,你需要更改路径。例如:@mock.patch('your_package.your_file.your_function.random.random')
*(2) 在这个案例中,get_random_words
函数调用了 random.random
三次。所以你需要在 mock_random.side_effect
中放入相同数量或更多的项目。如果放的项目少了,就会出现 StopIteration
错误。
4
你可以使用unittest.mock
库来替换掉random()
这个函数。这个库是从Python 3.3版本开始就有的,如果你用的是旧版本,可以单独安装mock
。
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)
6
这里是关于如何“模拟”random.random()
这个函数的内容,简单来说,就是在测试的时候用一个假的版本来代替它。这样做的好处是可以控制输出,让测试变得更简单。下面是一个例子:
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)]))