测试Click应用程序¶
对于基本测试,Click提供 click.testing
模块,它提供测试功能,帮助您调用命令行应用程序并检查其行为。
这些工具真的应该只用于测试,因为它们为了简单而改变了整个解释器的状态,并且不以任何方式是线程安全的!
基本测试¶
测试Click应用程序的基本功能是 CliRunner
它可以作为命令行脚本调用命令。这个 CliRunner.invoke()
方法单独运行命令行脚本,并将输出捕获为字节和二进制数据。
返回值为 Result
对象,其中附加了捕获的输出数据、退出代码和可选异常:
hello.py¶
import click
@click.command()
@click.argument('name')
def hello(name):
click.echo(f'Hello {name}!')
test_hello.py¶
from click.testing import CliRunner
from hello import hello
def test_hello_world():
runner = CliRunner()
result = runner.invoke(hello, ['Peter'])
assert result.exit_code == 0
assert result.output == 'Hello Peter!\n'
对于子命令测试,必须在 args 参数 CliRunner.invoke()
方法:
sync.py¶
import click
@click.group()
@click.option('--debug/--no-debug', default=False)
def cli(debug):
click.echo(f"Debug mode is {'on' if debug else 'off'}")
@cli.command()
def sync():
click.echo('Syncing')
test_sync.py¶
from click.testing import CliRunner
from sync import cli
def test_sync():
runner = CliRunner()
result = runner.invoke(cli, ['--debug', 'sync'])
assert result.exit_code == 0
assert 'Debug mode is on' in result.output
assert 'Syncing' in result.output
传递给的其他关键字参数 .invoke()
将用于构造初始上下文对象。例如,如果要针对固定的终端宽度运行测试,可以使用以下内容:
runner = CliRunner()
result = runner.invoke(cli, ['--debug', 'sync'], terminal_width=60)
文件系统隔离¶
对于具有文件系统操作的基本命令行工具 CliRunner.isolated_filesystem()
方法可用于将当前工作目录设置为新的空文件夹。
cat.py¶
import click
@click.command()
@click.argument('f', type=click.File())
def cat(f):
click.echo(f.read())
test_cat.py¶
from click.testing import CliRunner
from cat import cat
def test_cat():
runner = CliRunner()
with runner.isolated_filesystem():
with open('hello.txt', 'w') as f:
f.write('Hello World!')
result = runner.invoke(cat, ['hello.txt'])
assert result.exit_code == 0
assert result.output == 'Hello World!\n'
经过 temp_dir
以控制创建临时目录的位置。在这种情况下,不会通过单击删除该目录。这对于与像Pytest这样管理临时文件的框架集成非常有用。
def test_keep_dir(tmp_path):
runner = CliRunner()
with runner.isolated_filesystem(temp_dir=tmp_path) as td:
...
输入流¶
测试包装器还可以用于为输入流(stdin)提供输入数据。这对于测试提示非常有用,例如:
prompt.py¶
import click
@click.command()
@click.option('--foo', prompt=True)
def prompt(foo):
click.echo(f"foo={foo}")
test_prompt.py¶
from click.testing import CliRunner
from prompt import prompt
def test_prompts():
runner = CliRunner()
result = runner.invoke(prompt, input='wau wau\n')
assert not result.exception
assert result.output == 'Foo: wau wau\nfoo=wau wau\n'
请注意,将模拟提示,以便它们也将输入数据写入输出流。如果需要隐藏输入,那么显然不会发生这种情况。