如何在单元测试调用的函数中模拟用户输入(使用Python 3的unittest)?例如,我有一个函数foo()
谁正在测试我的输出。在foo()
函数中,它要求用户输入:
x = input(msg)
输出基于输入:
print("input: {0}".format(x))
我希望我的单元测试运行foo()
,输入一个输入并将结果与预期结果进行比较。
答案 0 :(得分:8)
当我尝试测试为用户输入提供对话框的代码时,我经常遇到这个问题,同样的解决方案应该适用于两者。您需要提供与测试作用域中名称input
绑定的新函数,其具有与标准input
函数相同的签名,该函数仅返回测试值而不实际提示用户。根据您的测试和代码的设置方式,这种注射可以通过多种方式完成,因此我将其留作读者练习,但您的替换方法将是简单的:
def my_test_input(message):
return 7
显然,如果相关,您也可以打开message
的内容,并返回您选择的数据类型。您还可以执行更灵活,更通用的操作,以便在许多情况下重复使用相同的替换方法:
def my_test_input(retval, message):
return retval
然后你会将部分函数注入input
:
import functools
test_input_a = functools.partial(my_test_input, retval=7)
test_input_b = functools.partial(my_test_input, retval="Foo")
将test_input_a
和test_input_b
作为带有message
个参数的函数,retval
参数已绑定。
答案 1 :(得分:3)
由于依赖性而难以测试某些组件,这通常是设计糟糕的标志。您的foo
函数不应该依赖于全局input
函数,而应该依赖于参数。然后,当您在生产环境中运行程序时,您将以这样的方式连接事物,即调用foo
并返回input
返回的结果。所以foo
应该是:
def foo(input):
# do something with input
这将使测试更容易。顺便说一句,如果您的测试具有IO
依赖性,则它们不再是单元测试,而是功能测试。请查看Misko Hevery's blog,了解有关测试的更多见解。
答案 2 :(得分:1)
我认为最好的方法是将input
函数包装到自定义函数上并模拟后者。就像这里描述的:python mocking raw input in unittests