pytest用于测试控制台脚本的插件
项目描述
pytest-console-scripts
pytest-console-scripts是一个pytest插件,用于在测试中运行Python脚本。它与subprocess.run()
非常相似,但它还有一个进程内模式,其中脚本由运行pytest
的解释器执行(使用一些沙盒技术)。
进程内模式显著减少了运行许多外部脚本的测试套件的运行时间。这加快了开发速度。在CI环境中,可以使用子进程模式确保脚本在由新解释器运行时也能正常工作(并且表现相同)。
需求
- Python 3.8+,或PyPy3
- Pytest 4.0或更高版本
安装
您可以通过从pip(位于PyPI)安装 "pytest-console-scripts"。
$ pip install pytest-console-scripts
通常,您会将它添加到 tox.ini
文件中的测试依赖项中(参见tox 文档)。
使用方法
此插件将运行通过 setup.py
中的 console_scripts
入口点安装的脚本、当前目录中的 Python 文件(或指定路径下的任何地方,如果提供了路径),以及路径中任何其他位置的 Python 脚本。它还将运行非 Python 脚本的可执行文件,但仅在子进程模式下(对于此目的使用 pytest-console-scripts
没有好处,您应仅使用 subprocess.run
)。
以下是一个具有 console_scripts
入口点的示例。假设我们有一个名为 foo
的 Python 包,其 setup.py
如下所示:
setup(
name='foo',
version='0.0.1',
py_modules=['foo'],
entry_points={
'console_scripts': ['foobar=foo:bar']
},
)
我们可以使用 pytest-console-scripts 来测试 foobar
脚本。
def test_foo_bar(script_runner):
result = script_runner.run(['foobar', '--version'])
assert result.returncode == 0
assert result.stdout == '3.2.1\n'
assert result.stderr == ''
script_runner.run('foobar --version', shell=True, check=True)
这将使用插件提供的 script_runner
修复件来运行脚本并捕获其输出。
script_runner.run
的参数是脚本的命令名以及要传递给它的任何命令行参数。此外,还可以使用以下关键字参数:
cwd
- 设置测试脚本的工作目录。env
- 一个字典,其中包含要使用而不是当前环境的环境变量。stdin
- 一个文件-like 对象,它将被管道传输到脚本的标准输入。check
- 如果returncode != 0
,则引发异常,默认为 False。shell
- 模拟 shell 执行,这对于简单情况应该效果良好,默认为 False。
也支持类型提示。您可以使用以下代码为修复件提供类型提示
from pytest_console_scripts import ScriptRunner
def test_foo_bar(script_runner: ScriptRunner) -> None:
...
配置脚本执行模式
在上面的示例中,foobar
脚本将以进程内模式运行(这是默认值)。这很快,适用于开发过程中的快速迭代。当我们对功能感到满意后,就到了运行脚本以模拟真实调用的子进程模式的时候了。有多种方法可以实现这一点。我们可以通过 pytest 配置来配置它(例如在 tox.ini
中)
[pytest]
script_launch_mode = subprocess
我们可以向 pytest 提供命令行选项(这将覆盖配置文件)
$ pytest --script-launch-mode=subprocess test_foobar.py
我们还可以标记单个测试以在特定模式下运行
@pytest.mark.script_launch_mode('subprocess')
def test_foobar(script_runner):
...
在这三种方法中,测试的标记优先于命令行选项,而命令行选项又覆盖了配置设置。所有三种都可以采取三种可能值:"inprocess"、"subprocess" 和 "both"(这将导致测试两次运行:一次在进程内模式,一次在子进程模式下)。
与模拟的交互
当使用 pytest-console-scripts
运行时,可以在控制台脚本内部模拟对象和函数,但仅限于进程内模式。当脚本以子进程模式运行时,它将由单独的 Python 解释器执行,并且测试无法在其中模拟任何内容。
模拟的另一个限制是,对于没有通过console_scripts
入口点安装的简单 Python 脚本,主脚本中对象内部的对象模拟将不起作用。原因是我们使用 $ python myscript.py
运行 myscript.py
时,脚本被导入到 __main__
命名空间,而不是 myscript
命名空间。我们针对 myscript.myfunction
的修补将不会影响在 __main__
命名空间中调用在相同文件中定义的 myfunction
时,该代码所看到的内容。
有关如何解决此问题的想法,请参阅此 stackoverflow 回答。
抑制脚本运行结果的打印
当涉及 pytest-console-scripts
的测试失败时,查看在其中执行的脚本的输出通常非常有用。我们试图提供帮助,并在返回 script_runner.run()
的结果之前打印出来。通常情况下,PyTest 捕获 测试运行期间的所有输出,除非某些测试失败,否则不会显示给用户。这正是我们想要的。
然而,在某些情况下,禁用输出捕获可能很有用,PyTest 提供了 方法 来实现这一点。当捕获被禁用时,所有测试运行结果都将被打印出来,这可能会使得检查其他测试输出变得更加困难。为了处理这个问题,pytest-console-scripts
有一个选项可以禁用脚本运行结果的打印。
$ pytest --hide-run-results test_foobar.py
也可以仅针对一次脚本运行禁用它。
result = script_runner.run('foobar', print_result=False)
当禁用脚本运行结果的打印时,即使测试失败,脚本输出也不会可见。遗憾的是,没有自动打印仅在测试失败时的方式,因为当脚本运行完成时,我们并不知道测试是否会失败。可以从测试中手动执行,使用以下方法:
result.print()
结合 --hide-run-results
或 print_result=False
,可以在捕获关闭时仅打印有趣的运行结果。
开发和测试中的包安装
由于 pytest-console-scripts
依赖于脚本位于路径中,它只能运行已安装(如果你对去除这个限制感兴趣,请查看 这个工单 以及特别是 这个评论)的包的控制台脚本。如果你想快速地在开发期间运行测试,额外的安装步骤将增加显著的开销并减慢你的速度。
有一种方法可以解决这个问题:使用 pip install -e .
以 开发模式 安装你的包。如果你使用 tox,你可以使用其中一个现有的虚拟环境(它们位于 .tox/
中)。否则,创建一个仅用于开发的 虚拟环境,激活它并运行 python setup.py develop
以开发模式安装你的包。每次你添加一个新的控制台脚本时,都需要重新安装,但除此之外,所有代码的更改都将立即被测试捕获。
贡献
欢迎贡献。可以使用 tox
运行测试,请在提交拉取请求之前确保覆盖率至少保持不变。
许可证
在 MIT 许可证的条款下分发,"pytest-console-scripts" 是免费和开源软件。
问题
如果你遇到任何问题,请 提交问题 并附带详细描述。
Pytest-console-scripts 是使用 Cookiecutter 以及 @hackebrot's Cookiecutter-pytest-plugin 模板最初生成的。
项目详情
下载文件
下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。
源代码分发
构建分发
pytest-console-scripts-1.4.1.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 5a826ed84cc0afa202eb9e44381d7d762f7bdda8e0c23f9f79a7f1f44cf4a895 |
|
MD5 | f28617c5043f2cf39ad0cea40132032d |
|
BLAKE2b-256 | a1852fbafaea1fa948497ef7f52574448e7ff99236c71a1519e312b8a2f01008 |
pytest_console_scripts-1.4.1-py3-none-any.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | ad860a951a90eca4bd3bd1159b8f5428633ba4ea01abd5c9526b67a95f65437a |
|
MD5 | d835ffe3059a32dd163f399ca527b977 |
|
BLAKE2b-256 | 3212149a568c244b58912350c7fd3b997ed6b57889a22098564cc43c3e511b76 |