Python单元测试If语句的预期输出

时间:2014-09-02 22:00:26

标签: python unit-testing if-statement

我正在创建一些单元测试。我对他们很陌生,只是想弄湿我的脚。因此,我正在尝试运行的当前测试是根据用户输入检查预期输出。所以我会用某种类型的值修补输入,然后检查我是否在最后收到了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

2 个答案:

答案 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!")