在单元测试中覆盖 python 函数局部变量
override python function-local variable in unittest
我在 python (2.7) 中有一个执行 foo 的方法,如果 foo 不起作用,5 分钟后放弃。
def keep_trying(self):
timeout = 300 #empirically derived, appropriate timeout
end_time = time.time() + timeout
while (time.time() < end_time):
result = self.foo()
if (result == 'success'):
break
time.sleep(2)
else:
raise MyException('useful msg here')
我知道 foo() 的一些可能结果,所以我使用模拟来伪造那些 return 值。问题是,我不希望测试在看到异常前 运行 5 分钟。
有没有办法覆盖本地的超时值?我希望只有几秒钟,这样我就可以看到循环尝试了几次,然后放弃并加注。
以下无效:
@patch.object(myClass.keep_trying, 'timeout')
@patch.object(myClass, 'foo')
def test_keep_trying(self, mock_foo, mock_timeout):
mock_foo.return_value = 'failed'
mock_timeout.return_value = 10 # raises AttributeError
mock_timeout = 10 # raises AttributeError
...
与其尝试模拟 timeout
的值,不如模拟 time.time()
的 return 值。
例如
@patch.object(time, 'time')
def test_keep_trying(self, mock_time):
mock_time.side_effect = iter([100, 200, 300, 400, 500, 600, 700, 800])
...
现在第一次调用 time.time()
时,您将获得值 100,因此它应该会在 while 循环几圈后超时。您还可以模拟 time.sleep
并只计算它被调用的次数以确保该部分代码正常工作。
另一种方法(与上述方法不完全正交)是允许用户将可选的超时关键字传递给函数:
def keep_trying(self, timeout=300):
...
这允许您在测试中指定您想要的任何超时(以及在不想等待 5 分钟的未来代码中;-)。
您不能模拟函数的局部变量。为了使您的代码更易于测试,请将其更改为,例如:
def keep_trying(self, timeout=300):
end_time = time.time() + timeout
# etc, as above
因此,运行 更短的超时测试变得微不足道!
我在 python (2.7) 中有一个执行 foo 的方法,如果 foo 不起作用,5 分钟后放弃。
def keep_trying(self):
timeout = 300 #empirically derived, appropriate timeout
end_time = time.time() + timeout
while (time.time() < end_time):
result = self.foo()
if (result == 'success'):
break
time.sleep(2)
else:
raise MyException('useful msg here')
我知道 foo() 的一些可能结果,所以我使用模拟来伪造那些 return 值。问题是,我不希望测试在看到异常前 运行 5 分钟。
有没有办法覆盖本地的超时值?我希望只有几秒钟,这样我就可以看到循环尝试了几次,然后放弃并加注。
以下无效:
@patch.object(myClass.keep_trying, 'timeout')
@patch.object(myClass, 'foo')
def test_keep_trying(self, mock_foo, mock_timeout):
mock_foo.return_value = 'failed'
mock_timeout.return_value = 10 # raises AttributeError
mock_timeout = 10 # raises AttributeError
...
与其尝试模拟 timeout
的值,不如模拟 time.time()
的 return 值。
例如
@patch.object(time, 'time')
def test_keep_trying(self, mock_time):
mock_time.side_effect = iter([100, 200, 300, 400, 500, 600, 700, 800])
...
现在第一次调用 time.time()
时,您将获得值 100,因此它应该会在 while 循环几圈后超时。您还可以模拟 time.sleep
并只计算它被调用的次数以确保该部分代码正常工作。
另一种方法(与上述方法不完全正交)是允许用户将可选的超时关键字传递给函数:
def keep_trying(self, timeout=300):
...
这允许您在测试中指定您想要的任何超时(以及在不想等待 5 分钟的未来代码中;-)。
您不能模拟函数的局部变量。为了使您的代码更易于测试,请将其更改为,例如:
def keep_trying(self, timeout=300):
end_time = time.time() + timeout
# etc, as above
因此,运行 更短的超时测试变得微不足道!