测试使用多个输入单击应用程序提示

时间:2018-05-29 20:10:49

标签: python unit-testing command-line-interface pytest python-click

我使用Click和Python编写了一个小命令行应用程序,我现在正在尝试编写测试(主要是为了学习如何测试点击应用程序,以便我可以继续测试我的那个实际开发)。

这是我正在尝试测试的功能:

@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/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'

对此的任何想法都将非常感谢!

1 个答案:

答案 0 :(得分:1)

要为测试运行器提供多个输入,您只需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。单击提供可以进行子类化的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:

要使用自定义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!")