python – 与argparse的Pytest:如何测试用户是否提示确认?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python – 与argparse的Pytest:如何测试用户是否提示确认?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5378字,纯文字阅读大概需要8分钟。
内容图文
![python – 与argparse的Pytest:如何测试用户是否提示确认?](/upload/InfoBanner/zyjiaocheng/728/d3c71a94698e46d0bc8e0c5edd5a552d.jpg)
我有一个CLI工具,并希望测试是否提示用户使用input()确认选择.这与在Python 2中使用raw_input()相同.
码
要测试的(释义)代码如下:
import sys
import argparse
def confirm():
notification_str = "Please respond with 'y' or 'n'"
while True:
choice = input("Confirm [Y/n]?").lower()
if choice in 'yes' or not choice:
return True
if choice in 'no':
return False
print(notification_str)
def parse_args(args):
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--destructive', action='store_true')
return parser.parse_args()
def main():
args = parse_args(sys.argv[1:])
if args.destructive:
if not confirm():
sys.exit()
do_stuff(args)
if __name__ == '__main__':
main()
题
我使用pytest作为我的框架.如何制作它以便我可以测试CLI中是否显示确认提示?如果我尝试比较stdout我得到错误:OSError:在捕获输出时从stdin读取.
我想确保:
>设置破坏性标志时会显示确认信息
>它不会出现
我将在另一个文件中使用以下代码:
import pytest
from module_name import main
def test_user_is_prompted_when_destructive_flag_is_set():
sys.argv['', '-d']
main()
assert _ # What the hell goes here?
def test_user_is_not_prompted_when_destructive_flag_not_set():
sys.argv['',]
main()
assert _ # And here too?
解决方法:
我建议使用confirm()函数开始测试是一种更好的单元测试策略.这允许在本地模拟输入和sys.stdio之类的东西.然后,一旦确认确认按预期工作,就可以编写测试以验证是否以特定方式调用.您可以为此编写测试,并在这些测试期间模拟confirm().
这是一个单元测试forconfirm(),它使用pytest.parametrize和mock来处理用户输入和输出:
码:
@pytest.mark.parametrize("from_user, response, output", [
(['x', 'x', 'No'], False, "Please respond with 'y' or 'n'\n" * 2),
('y', True, ''),
('n', False, ''),
(['x', 'y'], True, "Please respond with 'y' or 'n'\n"),
])
def test_get_from_user(from_user, response, output):
from_user = list(from_user) if isinstance(from_user, list) else [from_user]
with mock.patch.object(builtins, 'input', lambda x: from_user.pop(0)):
with mock.patch('sys.stdout', new_callable=StringIO):
assert response == confirm()
assert output == sys.stdout.getvalue()
这是如何运作的?
pytest.mark.parametrize允许在条件下多次调用测试函数.以下是4个简单的步骤,它们将测试确认中的大部分功能:
@pytest.mark.parametrize("from_user, response, output", [
(['x', 'x', 'No'], False, "Please respond with 'y' or 'n'\n" * 2),
('y', True, ''),
('n', False, ''),
(['x', 'y'], True, "Please respond with 'y' or 'n'\n"),
])
mock.patch可用于临时替换模块中的功能(以及其他用途).在这种情况下,它用于替换input和sys.stdout以允许注入用户输入和捕获打印的字符串
with mock.patch.object(builtins, 'input', lambda x: from_user.pop(0)):
with mock.patch('sys.stdout', new_callable=StringIO):
最后运行测试中的函数并验证函数的输出和打印的任何字符串:
assert response == confirm()
assert output == sys.stdout.getvalue()
测试代码(测试代码):
import sys
from io import StringIO
import pytest
from unittest import mock
import builtins
def confirm():
notification_str = "Please respond with 'y' or 'n'"
while True:
choice = input("Confirm [Y/n]?").lower()
if choice in 'yes' or not choice:
return True
if choice in 'no':
return False
print(notification_str)
@pytest.mark.parametrize("from_user, response, output", [
(['x', 'x', 'No'], False, "Please respond with 'y' or 'n'\n" * 2),
('y', True, ''),
('n', False, ''),
(['x', 'y'], True, "Please respond with 'y' or 'n'\n"),
])
def test_get_from_user(from_user, response, output):
from_user = list(from_user) if isinstance(from_user, list) \
else [from_user]
with mock.patch.object(builtins, 'input', lambda x: from_user.pop(0)):
with mock.patch('sys.stdout', new_callable=StringIO):
assert response == confirm()
assert output == sys.stdout.getvalue()
pytest.main('-x test.py'.split())
结果:
============================= test session starts =============================
platform win32 -- Python 3.6.3, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: C:\Users\stephen\Documents\src\testcode, inifile:
collected 4 items
test.py .... [100%]
========================== 4 passed in 0.15 seconds ===========================
测试电话确认():
要测试在预期时调用confirm,并且程序在调用时按预期响应,可以使用unittest.mock来模拟confirm().
注意:在通常的unittest方案中,确认将在不同的文件中,并且mock.patch可以以类似的方式用于在此示例中修补sys.argv的方式.
检查确认调用的测试代码():
import sys
import argparse
def confirm():
pass
def parse_args(args):
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--destructive', action='store_true')
return parser.parse_args()
def main():
args = parse_args(sys.argv[1:])
if args.destructive:
if not confirm():
sys.exit()
import pytest
from unittest import mock
@pytest.mark.parametrize("argv, called, response", [
([], False, None),
(['-d'], True, False),
(['-d'], True, True),
])
def test_get_from_user(argv, called, response):
global confirm
original_confirm = confirm
confirm = mock.Mock(return_value=response)
with mock.patch('sys.argv', [''] + argv):
if called and not response:
with pytest.raises(SystemExit):
main()
else:
main()
assert confirm.called == called
confirm = original_confirm
pytest.main('-x test.py'.split())
结果:
============================= test session starts =============================
platform win32 -- Python 3.6.3, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: C:\Users\stephen\Documents\src\testcode, inifile:
collected 3 items
test.py ... [100%]
========================== 3 passed in 3.26 seconds ===========================
enter code here
内容总结
以上是互联网集市为您收集整理的python – 与argparse的Pytest:如何测试用户是否提示确认?全部内容,希望文章能够帮你解决python – 与argparse的Pytest:如何测试用户是否提示确认?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。