Python单元测试中If语句的预期输出
我现在正在创建一些单元测试。我对这个还比较陌生,只是在尝试入门。所以我现在要运行的测试是根据用户输入检查预期的输出。我会用某种值来替代输入,然后检查最后是否收到了标准输出的信息。听起来有点复杂,但我希望有人能帮忙。以下是我的运行代码。
def main():
Attack = input("Are we being attacked?!")
if(Attack == "yes"):
print("We are being attacked! Attack Back!")
在上面的例子中,我会测试打印语句,因为我会把用户输入替换成“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()
显然,这样做是不行的。那么我缺少了什么呢?非常感谢大家的帮助!
编辑:这是我运行测试时收到的错误信息。我理解这个错误,只是不知道该怎么修复它。
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
2 个回答
2
除了@chepner的回答,你还需要使用unittest.TestCase
里的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!")
如果你觉得装饰器很复杂,其实你也可以这样做:
class TestStuff(unittest.TestCase):
def test_output(self):
with patch('builtins.input', return_value='yes'), \
patch('builtins.print') as new_print:
main()
new_print.assert_called_with("We are being attacked! Attack Back!")
2
用patch
装饰的函数会多一个参数,这个参数是Mock
。你需要
@patch('builtins.input', return_value='yes')
def test_output(self, m):
在这里,第二个参数m
会指向一个Mock
对象,这个对象会在调用test_output
时替代input
。
在pydoc unittest.mock
的patch
部分提到:
如果
patch
作为装饰器使用,并且省略了new
,那么创建的mock会作为额外的参数传递给被装饰的函数。