#python #command-line-interface #python-unittest #python-click
#python #интерфейс командной строки #python-unittest #python-щелчок
Вопрос:
Я пытаюсь протестировать создание исключений с помощью команды, реализованной с помощью пакета Click.
Это моя команда:
@click.option(
'--bucket_name',
...)
@click.option(
'--group_id',
...)
@click.option(
'--artifact_id',
...)
@click.option(
'--version',
...)
@click.option(
'--artifact_dir',
required=False,
default='downloads/artifacts/',
...)
@click.command()
def download_artifacts(
bucket_name,
group_id, artifact_id, version,
artifact_dir
):
logger.info(
f"bucket_name: {bucket_name}, "
f"group_id: {group_id}, "
f"artifact_id: {artifact_id}, "
f"version: {version}, "
f"artifact_dir: {artifact_dir}, "
)
if not artifact_dir.endswith('/'):
raise ValueError(
"Enter artifact_dir ending with '/' ! artifact_dir: "
f"{artifact_dir}")
...
Это мой тестовый код, assertRaises
который не работает:
def test_download_artifacts_invalid_dir(
self,
):
runner = CliRunner()
with self.assertRaises(ValueError):
result = runner.invoke(
download_artifacts,
'--bucket_name my_bucket
--group_id gi
--artifact_id ai
--version 1.0.0
--artifact_dir artifact_dir'.split(),
input='5')
Утверждение завершается ошибкой, и E AssertionError: ValueError not raised
вместо этого оно выдает.
Я нашел этот способ тестирования, который проходит, но он не кажется очень элегантным:
def test_download_artifacts_invalid_dir(
self,
):
runner = CliRunner()
result = runner.invoke(
download_artifacts,
'--bucket_name my_bucket
--group_id gi
--artifact_id ai
--version 1.0.0
--artifact_dir artifact_dir'.split(),
input='5')
print(f"result.exception: {result.exception}")
assert "Enter artifact_dir ending" in str(result.exception)
Ответ №1:
Два способа проверки исключений с помощью click.CliRunner()
Первый метод указан в ДОКУМЕНТАХ:
Базовое тестирование
Основной функциональностью для тестирования приложений Click является CliRunner, который может вызывать команды в виде сценариев командной строки. Метод CliRunner.invoke() запускает сценарий командной строки изолированно и фиксирует выходные данные как в виде байтов, так и в виде двоичных данных.
Возвращаемое значение представляет собой объект [Result], к которому прикреплены захваченные выходные данные, код выхода и необязательное исключение.
result = runner.invoke(throw_value_error)
assert isinstance(result.exception, ValueError)
Второй метод заключается в установке catch_exceptions=False
параметра на CliRunner.invoke()
runner.invoke(..., catch_exceptions=False)
Тестовый код
import click.testing
import pytest
@click.command()
def throw_value_error():
raise ValueError("This is My Message!")
def test_catch_value_error():
"""Read the CliRunner exception report"""
runner = click.testing.CliRunner()
result = runner.invoke(throw_value_error)
assert isinstance(result.exception, ValueError)
assert 'My Message' in str(result.exception)
def test_throw_value_error():
"""Have the CliRunner not catch my exception"""
runner = click.testing.CliRunner()
with pytest.raises(ValueError):
runner.invoke(throw_value_error, catch_exceptions=False)
Результаты тестирования
============================= test session starts ==============================
platform linux -- Python 3.7.7, pytest-6.2.1 -- /usr/bin/python
collecting ... collected 2 item
tests/test_api_authz.py::test_catch_value_error PASSED [ 50%]
tests/test_api_authz.py::test_throw_value_error PASSED [100%]
============================== 2 passed in 0.05s ===============================