使用多个输入测试 Click 应用程序提示
Testing Click application prompting with multiple inputs
我已经使用 Click 和 Python 编写了一个小型命令行应用程序,我现在正在尝试为其编写测试(主要是为了学习如何测试 Click 应用程序,以便我可以继续测试我实际开发的那个)。
这是我要测试的函数:
@click.group()
def main():
pass
@main.command()
@click.option('--folder', '-f', prompt="What do you want to name the folder? (No spaces please)")
def create_folder(folder):
while True:
if " " in folder:
click.echo("Please enter a name with no spaces.")
folder = click.prompt("What do you want to name the folder?", type=str)
if folder in os.listdir():
click.echo("This folder already exists.")
folder = click.prompt("Please choose a different name for the folder")
else:
break
os.mkdir(folder)
click.echo("Your folder has been created!")
我正在尝试使用来自 Click 的内置测试(http://click.pocoo.org/6/testing/ and http://click.pocoo.org/6/api/#testing 了解更多详细信息)以及 pytest 来测试它。这在我测试可接受的文件夹名称(即没有空格且尚不存在的文件夹名称)的情况下效果很好。见下文:
import clicky # the module we're testing
import os
from click.testing import CliRunner
import click
import pytest
input sys
runner = CliRunner()
folder = "myfolder"
folder_not = "my folder"
question_create = "What do you want to name the folder? (No spaces please): "
echoed = "\nYour folder has been created!\n"
def test_create_folder():
with runner.isolated_filesystem():
result = runner.invoke(clicky.create_folder, input=folder)
assert folder in os.listdir()
assert result.output == question_create + folder + echoed
我现在想测试这个功能,如果我提供了一个不允许的文件夹名称,比如带空格的,然后在提示我不能有空格后,我会提供一个可以接受的文件夹名称。但是,我不知道如何让 click.runner
接受多个输入值,这是我能想到的唯一方法。我也愿意使用 unittest 模拟,但我不确定如何将其集成到 Click 进行测试的方式中,除了这个问题之外,到目前为止效果很好。这是我对多个输入的尝试:
def test_create_folder_not():
with runner.isolated_filesystem():
result = runner.invoke(clicky.create_folder, input=[folder_not, folder]) # here i try to provide more than one input
assert result.output == question_create + folder_not + "\nPlease enter a name with no spaces.\n" + "What do you want to name the folder?: " + folder + echoed
我试图通过将它们放在一个列表中来提供多个输入,就像我看到的模拟一样,但是我得到了这个错误:
'list' object has no attribute 'encode'
如有任何想法,我们将不胜感激!
要为测试运行程序提供多个输入,您可以简单地 join()
输入和 \n
一起使用,如下所示:
代码:
result = runner.invoke(clicky.create_folder,
input='\n'.join([folder_not, folder]))
结果:
============================= test session starts =============================
platform win32 -- Python 3.6.3, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: \src\testcode, inifile:
collected 2 items
testit.py .. [100%]
========================== 2 passed in 0.53 seconds ===========================
使用 click.ParamType
的替代实现
不过,我建议您可以使用 ParamType
来提示所需的文件名属性。 Click 提供了一个可以被子类化的 ParamType
,然后传递给 click.option()
。然后可以通过单击来处理格式检查和重新提示。
您可以将 ParamType 子类化为:
import click
class NoSpacesFolder(click.types.StringParamType):
def convert(self, value, param, ctx):
folder = super(NoSpacesFolder, self).convert(value, param, ctx)
if ' ' in folder:
raise self.fail("No spaces allowed in selection '%s'." %
value, param, ctx)
if folder in os.listdir():
raise self.fail("This folder already exists.\n"
"Please choose another name.", param, ctx)
return folder
使用参数类型:
要使用自定义 ParamType,请将其传递给 click.option()
,例如:
@main.command()
@click.option(
'--folder', '-f', type=NoSpacesFolder(),
prompt="What do you want to name the folder? (No spaces please)")
def create_folder(folder):
os.mkdir(folder)
click.echo("Your folder has been created!")
我已经使用 Click 和 Python 编写了一个小型命令行应用程序,我现在正在尝试为其编写测试(主要是为了学习如何测试 Click 应用程序,以便我可以继续测试我实际开发的那个)。
这是我要测试的函数:
@click.group()
def main():
pass
@main.command()
@click.option('--folder', '-f', prompt="What do you want to name the folder? (No spaces please)")
def create_folder(folder):
while True:
if " " in folder:
click.echo("Please enter a name with no spaces.")
folder = click.prompt("What do you want to name the folder?", type=str)
if folder in os.listdir():
click.echo("This folder already exists.")
folder = click.prompt("Please choose a different name for the folder")
else:
break
os.mkdir(folder)
click.echo("Your folder has been created!")
我正在尝试使用来自 Click 的内置测试(http://click.pocoo.org/6/testing/ and http://click.pocoo.org/6/api/#testing 了解更多详细信息)以及 pytest 来测试它。这在我测试可接受的文件夹名称(即没有空格且尚不存在的文件夹名称)的情况下效果很好。见下文:
import clicky # the module we're testing
import os
from click.testing import CliRunner
import click
import pytest
input sys
runner = CliRunner()
folder = "myfolder"
folder_not = "my folder"
question_create = "What do you want to name the folder? (No spaces please): "
echoed = "\nYour folder has been created!\n"
def test_create_folder():
with runner.isolated_filesystem():
result = runner.invoke(clicky.create_folder, input=folder)
assert folder in os.listdir()
assert result.output == question_create + folder + echoed
我现在想测试这个功能,如果我提供了一个不允许的文件夹名称,比如带空格的,然后在提示我不能有空格后,我会提供一个可以接受的文件夹名称。但是,我不知道如何让 click.runner
接受多个输入值,这是我能想到的唯一方法。我也愿意使用 unittest 模拟,但我不确定如何将其集成到 Click 进行测试的方式中,除了这个问题之外,到目前为止效果很好。这是我对多个输入的尝试:
def test_create_folder_not():
with runner.isolated_filesystem():
result = runner.invoke(clicky.create_folder, input=[folder_not, folder]) # here i try to provide more than one input
assert result.output == question_create + folder_not + "\nPlease enter a name with no spaces.\n" + "What do you want to name the folder?: " + folder + echoed
我试图通过将它们放在一个列表中来提供多个输入,就像我看到的模拟一样,但是我得到了这个错误:
'list' object has no attribute 'encode'
如有任何想法,我们将不胜感激!
要为测试运行程序提供多个输入,您可以简单地 join()
输入和 \n
一起使用,如下所示:
代码:
result = runner.invoke(clicky.create_folder,
input='\n'.join([folder_not, folder]))
结果:
============================= test session starts =============================
platform win32 -- Python 3.6.3, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: \src\testcode, inifile:
collected 2 items
testit.py .. [100%]
========================== 2 passed in 0.53 seconds ===========================
使用 click.ParamType
的替代实现
不过,我建议您可以使用 ParamType
来提示所需的文件名属性。 Click 提供了一个可以被子类化的 ParamType
,然后传递给 click.option()
。然后可以通过单击来处理格式检查和重新提示。
您可以将 ParamType 子类化为:
import click
class NoSpacesFolder(click.types.StringParamType):
def convert(self, value, param, ctx):
folder = super(NoSpacesFolder, self).convert(value, param, ctx)
if ' ' in folder:
raise self.fail("No spaces allowed in selection '%s'." %
value, param, ctx)
if folder in os.listdir():
raise self.fail("This folder already exists.\n"
"Please choose another name.", param, ctx)
return folder
使用参数类型:
要使用自定义 ParamType,请将其传递给 click.option()
,例如:
@main.command()
@click.option(
'--folder', '-f', type=NoSpacesFolder(),
prompt="What do you want to name the folder? (No spaces please)")
def create_folder(folder):
os.mkdir(folder)
click.echo("Your folder has been created!")