Рубрики
Без рубрики

Урожайность для оказания постижимости в Python

(Это кросспуст из моего блога: https: //blog.meadsteve.dev/programming/2021/01/01/yealling-fortes … Помечено Python, тестирование, генераторы, выход.

(Это кросспания из моего блога: https://blog.meadsteve.dev/programming/2021/01/01/yepling-formilective/ )

Я писал небольшой инструмент CLI и хотел попробовать Типер Отказ Я большой поклонник быстрой API, поэтому я думал, что библиотека CLI из того же автора стоило взгляда. Этот пост блога будет покрывать шаблон, который я закончил использовать, чтобы помочь с тестированием.

Приложение и первая попытка тестов

Я не буду идти в слишком много подробностей о моей реальной проблеме, но я оказался чем-то вроде следующего:

import typer

def my_command(some_input: str):
    typer.echo(f"Starting up")
    # Do the first thing
    typer.echo(f"Result of first thing was X")
    # Do the second  thing
    typer.echo(f"Result of second thing was X")
    # Do some clean up
    typer.echo(f"All done")

if __name__ == "__main__":
    typer.run(my_command)

Значение в коде я писал, был выходом Typer.echo . Поэтому я хотел проверить это. Первоначально в моих тестах я был заплаткой обезьян Typer.echo и утверждать, что это соответствует тому, что Я хотел. Это было в порядке, но я не люблю исправления обезьян с издевательствами, как это часто становится очень запутанный и сложный.

Решение? Уступая.

Так как у меня уже была функция, представляющая призыв моей команды, я думал, что это будет Действительно приятно, если бы я мог просто вернуть вывод. Тогда я мог бы назвать функцию и утверждать что это выпустило то, что я хотел. Тем не менее, учитывая, что вполне значительные задержки могут происходит между каждой из моих эхо-заявлений, которые я действительно не хотел ждать до конца Чтобы получить весь мой выход. Так вместо этого доходность казалось хорошим кандидатом. Я обновил свой код смотреть что-то подобное:

@dataclass
class Echo:
    message: str

def my_command(some_input: str):
    yield Echo(f"Starting up")
    # Do the first thing
    yield Echo(f"Result of first thing was X")
    # Do the second  thing
    yield Echo(f"Result of second thing was X")
    # Do some clean up
    yield Echo(f"All done")

Теперь моя функция была генератором. Код выглядел почти идентичным, что было приятно. Мне нужно было добавить слой сверху, чтобы запустить этот генератор Но это было не слишком сложно:

import typer

def run_cli(generator_func):
    for output_line in generator_func():
        typer.echo(output_line.message)

И теперь мои тестовые случаи могут выглядеть так:

def test_something():
    actual = list(my_command("input"))
    expected = [
        Echo("first message"), 
        Echo("second message"), 
        Echo("etc.")
    ]
    assert actual == expected

Я считаю это успехом. Мои тесты стали намного проще, что было моей первоначальной целью. Кроме того, my_command Функция потеряла свою зависимость от Типер Библиотека и стало Агностик к тому, как ввод отображается пользователю (хотя это не было действительно моей первоначальной целью).

Оригинал: “https://dev.to/meadsteve/yielding-for-testability-in-python-1j20”