我知道如何用单个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"