如何测试具有多个“输入”功能的交互式 python 脚本
How to test interactive python script with multiple `input` functions
我知道如何使用单个 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"
您可以为您的用例定义您想要的确切输出,而不是任意传递是和否值,从而将其推进到下一步
@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"
我知道如何使用单个 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"
您可以为您的用例定义您想要的确切输出,而不是任意传递是和否值,从而将其推进到下一步
@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"