我正在创建一些单元测试。我对他们很陌生,只是想弄湿我的脚。因此,我正在尝试运行的当前测试是根据用户输入检查预期输出。所以我会用某种类型的值修补输入,然后检查我是否在最后收到了stdout消息。听起来有点令人困惑,但我希望有人可以提供帮助。这是我的运行代码。
def main():
Attack = input("Are we being attacked?!")
if(Attack == "yes"):
print("We are being attacked! Attack Back!")
所以在上面的例子中,我将测试print语句,因为我将修改值为yes的用户输入。这是我的测试套件
import unittest
from unittest.mock import patch
import io
import sys
from RunFile import main
class GetInputTest(unittest.TestCase):
@patch('builtins.input', return_value='yes')
def test_output(self):
saved_stdout = sys.stdout
try:
out = io.StringIO()
sys.stdout = out
main()
output = out.getvalue().strip()
self.assertEqual(output, "We are being attacked! Attack Back!")
finally:
sys.stdout = saved_stdout
if __name__ == "__main__":
unittest.main()
所以这显然不起作用。那我错过了什么?提前谢谢大家!
EDITED:这是我运行测试时收到的错误消息。我理解错误,只是不知道如何解决它。
Error
Traceback (most recent call last):
File "C:\Python33\lib\unittest\mock.py", line 1087, in patched
return func(*args, **keywargs)
TypeError: test_output() takes 1 positional argument but 2 were given
答案 0 :(得分:2)
由patch
修饰的功能会将Mock
作为附加参数。你需要
@patch('builtins.input', return_value='yes')
def test_output(self, m):
其中第二个参数m
将是Mock
对象的引用,该对象在调用input
时替换test_output
。
来自pydoc unittest.mock
下的patch
:
如果
patch
用作装饰器而new
是。{ 省略,创建的mock作为额外参数传入 装饰功能。
答案 1 :(得分:2)
除了@Chepner的回答,你还需要使用unittest.TestCase
的{{1}}方法,而不是断言自己(双关语)
assert
然而,这可能不是您尝试做的最佳方式。你知道,你可以修补多个内置版本。
class TestStuff(unittest.TestCase):
@patch('builtins.input', return_value='yes')
def test_output(self, new_input):
try:
out = io.StringIO()
sys.stdout = out
main()
output = out.getvalue().strip()
self.assertEqual(output, "We are being attacked! Attack Back!")
finally:
sys.stdout = saved_stdout
如果装饰者很可怕,你甚至可以这样做:
class TestStuff(unittest.TestCase):
@patch('builtins.input', return_value='yes')
@patch('builtins.print')
def test_output(self, new_print, new_input):
# the mocked functions are passed in opposite order
# to where they're decorated
main()
new_print.assert_called_with("We are being attacked! Attack Back!")