これはここやプログラマーのスタックエクスチェンジに最適なのかどうか分かりませんが、最初にここで試してみて、それが適切でない場合はクロスポストします。クリックベースのCLIアプリケーションの単体テストでコンポーネントを模擬する方法は?
私は最近、Webサービスを開発しました。私はPythonベースのコマンドラインインターフェイスを作成して、やりとりしやすくしています。私は単純なスクリプト目的のためにPythonをしばらく使用してきましたが、私はCLIアプリケーションを含む本格的なパッケージを作成するのには慣れていません。
CLIアプリケーションの作成に役立つさまざまなパッケージを調査しましたが、clickを使用して解決しました。私が心配しているのは、徹底的にアプリケーションを構築してtestableにする前に、どうすれば実際にそれをまとめるのか、それをクリックするとどのように役立つのかということです。私も検討してclick's documentation on testingを読んだ
relevant part of the APIと私はシンプルな機能をテストするためにこれを使用するために管理してきた一方で、私が処理するかどうかはわかりません(私のCLIに引数として渡されたときに--version
と--help
作業を検証します)より高度なテストケース
私が今テストしようとしている具体的な例を提供します。私は...アーキテクチャの次の並べ替えを持っている自分のアプリケーションのためにCommunicationService
を接続し、直接HTTP経由のWebサービスとの通信に関わるすべてのロジックをカプセル化
を...計画しています。私のCLIは、Webサービスのホスト名とポートのデフォルトを提供していますが、ユーザーはこれらを上書きできるようにする必要があり、明示的なコマンドライン引数、設定ファイルを書くか、環境変数の設定によって:
@click.command(cls=TestCubeCLI, help=__doc__)
@click.option('--hostname', '-h',
type=click.STRING,
help='TestCube Web Service hostname (default: {})'.format(DEFAULT_SETTINGS['hostname']))
@click.option('--port', '-p',
type=click.IntRange(0, 65535),
help='TestCube Web Service port (default: {})'.format(DEFAULT_SETTINGS['port']))
@click.version_option(version=version.__version__)
def cli(hostname, port):
click.echo('Connecting to TestCube Web Service @ {}:{}'.format(hostname, port))
pass
def main():
cli(default_map=DEFAULT_SETTINGS)
は私がテストしたいというユーザーの指定した場合Controller
は、デフォルトではなく、これらの設定を使用してCommunicationService
をインスタンス化します。
私はこれを行うための最善の方法は、これらの線に沿って何かだろうと想像:私は適切にこのケースを処理する方法についてのアドバイスを得ることができる場合、私はうまくいけば、それを拾うことができるはずです
def test_cli_uses_specified_hostname_and_port():
hostname = '0.0.0.0'
port = 12345
mock_comms = mock(CommunicationService)
# Somehow inject `mock_comms` into the application to make it use that instead of 'real' comms service.
result = runner.invoke(testcube.cli, ['--hostname', hostname, '--port', str(port)])
assert result.exit_code == 0
assert mock_comms.hostname == hostname
assert mock_comms.port == port
とCLIの他のすべての部分をテスト可能にするために同じテクニックを使用してください。
何が価値がある、私は現在、私のテストのためにpytestを使用していますし、これは私がこれまで持っているテストの範囲であるために:私は私がやって1つの方法を見つけたと思う
import pytest
from click.testing import CliRunner
from testcube import testcube
# noinspection PyShadowingNames
class TestCLI(object):
@pytest.fixture()
def runner(self):
return CliRunner()
def test_print_version_succeeds(self, runner):
result = runner.invoke(testcube.cli, ['--version'])
from testcube import version
assert result.exit_code == 0
assert version.__version__ in result.output
def test_print_help_succeeds(self, runner):
result = runner.invoke(testcube.cli, ['--help'])
assert result.exit_code == 0