【问题标题】:Python testing using mock library for user input in a loop使用模拟库在循环中进行用户输入的 Python 测试
【发布时间】:2015-09-20 16:15:27
【问题描述】:

我正在尝试使用模拟库来测试一段代码。在此代码中,用户原始输入在 for 循环中被接受,如下所示。我已经编写了测试用例test_apple_record,它可以为托盘编号提供单个用户输入值。

但是,对于 for 循环中的每次迭代,它只采用与预期相同的值 (5)。

问题是:如何为每次迭代提供不同的值?例如,对于 i=0、1 和 2 的托盘编号,具体值为 5、6 和 7。

class SomeClass(unittest.TestCase):    
    def apple_counter(self):
        apple_record = {}
        for i in range(3):
            apple_tray = input("enter tray number:")
            apple_record[apple_tray]  =  (i+1)*10
            print("i=%d, apple_record=%s"%(i, apple_record))

    def test_apple_record(self):
        with mock.patch('builtins.input', return_value='5'):
            self.apple_counter()

【问题讨论】:

    标签: python unit-testing mocking


    【解决方案1】:

    您可以将side_effect 参数与可迭代对象一起使用以提供返回值:

    with mock.patch('builtins.input', side_effect=[5, 6, 7]):
        self.apple_counter()
    

    docs

    如果 side_effect 是一个可迭代对象,那么对模拟的每次调用都会从可迭代对象返回下一个值。

    【讨论】:

      【解决方案2】:

      原来我是在重新发明轮子。请改用side_effect 参数。无论如何都要在此处留下修改后的版本,以防有人想做一些花哨的事情。

      要使用不同的函数,请使用 patchnew_callable 关键字参数

      with mock.patch('builtins.input', new_callable=lambda *x: random.randrange(0,10)):
          do_stuff()
      

      然而,这意味着值是完全随机的,这对于测试来说是不可取的,因为这意味着测试不是确定性的,并且可能会失败或不完全是偶然的。此外,您可能希望 input() 函数发出生成的非随机值,例如命令序列或类似的序列。为此,我认为最简单的方法是生成器函数。

      def input_generator(): # generate squares as an example
          a = 0
          while True:
              yield a**2
              a += 1
      
      g = input_generator()
      
      with mock.patch('builtins.input', lambda *x: next(g)):
          do_stuff()
      

      【讨论】:

        猜你喜欢
        • 2019-02-28
        • 2011-09-18
        • 1970-01-01
        • 2011-05-14
        • 1970-01-01
        • 2021-12-25
        • 2020-01-22
        • 1970-01-01
        相关资源
        最近更新 更多