如何测试具有多个' input '函数的交互式python脚本



我知道如何用单个input函数测试python函数,但我似乎无法弄清楚如何在其中测试多个input函数的python函数。

请参阅下面的最小示例代码test.py:

import pytest
import mock
import builtins

def unsubscribe():
    if input("are you unsubscribing? [y/n]") == "n":
        return "we are glad to have you back"
    else:
        if input("would you like a 20%% off discount code? [y/n]") == "y":
            return "your discount code is SAVE20, and we are glad you have you back"
        else:
            return "we are sad to see you go"

def test_unsubscribe():
    with mock.patch.object(builtins, 'input', lambda _: 'n'):
        assert unsubscribe() == "we are glad to have you back"
    with mock.patch.object(builtins, 'input', lambda _: 'y'):
        assert unsubscribe() == "your discount code is SAVE20, and we are glad you have you back"
    # what to put here to test the below
    #    assert unsubscribe() == "we are sad to see you go"

在目前的方法中,模拟补丁将每个input函数替换为所有n或所有y,这导致第一输入y和第二输入n的控制流不可达。单元测试包含多个input函数的python函数的正确方法是什么?

您可以使用side_effect。Side_effect接受一个列表作为输入,并按元素的顺序提供结果。

假设测试和源代码在不同的目录

@patch('sample.input')
def test_options(mock_input):
   mock_input.side_effect = ['y', 'y']
   result = unsubscribe()
   assert result == "your discount code is SAVE20, and we are glad you have you back"

您可以通过为您的用例定义您想要的确切输出来进行下一步,而不是任意传递yes和no值

@patch('sample.input')
def test_options(mock_input):
   def input_side_effect(*args, **kwargs):
       m = {
           'are you unsubscribing? [y/n]': 'y',
           'would you like a 20%% off discount code? [y/n]': 'y',
       }.get(args[0])
       if m:
           return m
       pytest.fail('This question is not expected')
   mock_input.side_effect = input_side_effect
   result = unsubscribe()
   assert result == "your discount code is SAVE20, and we are glad you have you back"

最新更新