模拟标准输入 - 在Python 3的多线(Mock standard input - multi

2019-09-27 23:48发布

我是新来的Python和使用python 3为我的学习一直。 我使用python的单元测试框架来测试我的代码。

问题: -

我需要进行单元测试该函数采用输入以下面的方式: -

def compare():
   a, b, c = input().strip().split(' ')
   d, e, f = input().strip().split(' ')
   # other code here

我使用下面的测试案例嘲笑输入: -

class TestCompare(unittest.TestCase):

   @patch("builtins.input", lambda: "1 2 3")
   @patch("builtins.input", lambda: "4 5 6")
   def test_compare(self):
      self.assertEqual(compare(), "1 1")

我现在面临的问题是,在测试运行情况下,当可变三联体的a,b,c和d,E,F具有相同的值 - 1,2,3

我一直试图找到一种方式来注入第二组输入运行我的测试,但徒劳无功。

任何有关上述帮助是极大的赞赏。

解决方案环境: - Python 3中

Answer 1:

该补丁装饰将确保打补丁函数始终返回值,如果后续调用必须是不同的,你的模拟对象必须有一种方法来模拟。 这最终是要复杂得多。

但是什么你能做的就是走一步降低,修补底层,这是标准的输入/输出层。 其他测试框架做了一个常见的策略是应对sys.stdinsys.stdout直接对象。 试想一下:

import unittest
from unittest.mock import patch

from io import StringIO

def compare():
    a, b, c = input().strip().split(' ')
    d, e, f = input().strip().split(' ')

    return '%s %s' % (a, d)

class TestCompareSysStdin(unittest.TestCase):

    @patch("sys.stdin", StringIO("1 2 3\n4 5 6"))
    def test_compare(self):
        self.assertEqual(compare(), "1 4")

执行

$ python -m unittest foo
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

当然,这个工作在一个较低的水平,所以选项有返回,在后续调用不同的值可能更适合的迭代器。



Answer 2:

你不能修补了两次这样的。 你必须一次修补它,与在随后的调用返回的值不同的对象。 下面是一个例子:

fake_input = iter(['1 2 3', '4 5 6']).__next__

@patch("builtins.input", fake_input)
def test_compare(self):
    ...


Answer 3:

你不能修补你的函数两次这样。 当你正在寻找嘲笑相同的功能,并使其在每次调用时返回不同的值,你应该使用side_effect 。

side_effect取值,在列表中的每个值是每一个函数被调用你的代码的时间返回的列表:

class TestCompare(unittest.TestCase):

    @patch("builtins.input", side_effect=["1 2 3", "4 5 6"])
    def test_compare(self, mock_input):
        self.assertEqual(compare(), "1 1") 


文章来源: Mock standard input - multi line in python 3