Тестирование Нажмите приложение, запрашивающее несколько входов - PullRequest
0 голосов
/ 29 мая 2018

Я написал небольшое приложение для командной строки с использованием 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/ и 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 принимать более одного входного значения, и я думаю, что это единственный способ заставить эту работу работать.Я также открыт для использования юнит-тестов юнит-тестов, но я не уверен, как интегрировать это в то, как 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 голосов
/ 30 мая 2018

Чтобы обеспечить более одного входа для тестового бегуна, вы можете просто 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:

Для использованияпользовательский 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!")
...