[英]How to test a Python CLI program with click, coverage.py, and Tox?
我正在使用click进行CLI程序,我想开始使用coverage.py添加一些代码覆盖率分析的测试。
我认为实现测试的一个好方法是使用子进程运行CLI本身。 但是,coverage.py报告零代码覆盖率,可能是因为子进程生成的Python实例没有coverage.py检测。
我发现这个链接说我可以在我的PYTHONPATH中删除sitecustomize.py
文件以始终强制Python开始覆盖测量,但我使用Tox来创建一个venv并运行测试。 我找不到任何处理此问题的Tox设置。
我发现这个答案说我应该通过coverage run
运行我的CLI,但看起来只有在给出Python脚本的路径时才有效,而我正在尝试通过setup.py
定义的入口点运行CLI 。 即我必须将测试代码中的所有命令行从myprogram
更改为coverage run myprogram/cli/cli.py
我宁愿不这样做,因为这不是我期望用户运行程序的方式。
所以看起来这两个选项是:
找出一种方法使sitecustomize.py
在Tox环境中工作,或者
测试代码中的所有命令行都使用脚本路径而不是入口点(从长远来看可能更容易,但会使测试更加脆弱和难以理解)。 想知道是否还有其他我想念的东西。
CliRunner和适当的单元测试框架是可行的方法。 下面是一个例子设置PyTest其使用PyTest 覆盖插件
from click.testing import CliRunner
from click_prog import hello
def test_hello_world():
runner = CliRunner()
result = runner.invoke(hello, ['--opt', 'An Option', 'An Arg'])
assert result.exit_code == 0
assert result.output == 'Opt: An Option Arg: An Arg\n'
result = runner.invoke(hello, ['An Arg'])
assert result.exit_code == 0
assert result.output == 'Opt: None Arg: An Arg\n'
if __name__ == '__main__':
test_hello_world()
import click
import sys
@click.command()
@click.option('--opt')
@click.argument('arg')
def hello(arg, opt):
"""A Simple program"""
click.echo('Opt: {} Arg: {}'.format(opt, arg))
if __name__ == '__main__':
hello(sys.argv[1:])
[pytest]
# -- recommended but optional:
# python_files = tests.py test_*.py *_tests.py
===================== test session starts =====================
platform darwin -- Python 3.6.5, pytest-3.7.1, py-1.5.4, pluggy-0.7.1
rootdir: /Users/strauch/dev/fix_windows, inifile: pytest.ini
plugins: xdist-1.22.5, forked-0.2, cov-2.6.0
collected 1 item
test_click.py . [100%]
---------- coverage: platform darwin, python 3.6.5-final-0 -----------
Name Stmts Miss Cover
------------------------------------
click_prog.py 8 1 88%
test_click.py 12 1 92%
------------------------------------
TOTAL 20 2 90%
================== 1 passed in 0.07 seconds ===================
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.