
本文旨在解决 pytest 从 4.x 升级到 5.x+ 后,`pytest.config` 被移除导致无法通过命令行标志条件运行或跳过特定测试的问题。我们将介绍如何利用 pytest 5.x+ 及更高版本中的自定义标记(`pytest.mark`)与 `-m` 命令行选项,优雅地实现对带有特定装饰器的测试进行灵活的选择性执行,从而避免大规模代码修改。此方法不仅保持了代码的简洁性,也提升了测试管理的效率和灵活性。
在 Pytest 4.x 版本中,开发者通常会利用 pytest.config.getoption 方法结合自定义装饰器来根据命令行参数动态控制特定测试的运行或跳过。例如,以下代码展示了如何定义一个 integration 装饰器,使其在 --integration 命令行标志不存在时自动跳过集成测试:
# common.py (Pytest 4.x 示例)
import pytest
integration = pytest.mark.skipif(
not pytest.config.getoption('--integration', False),
reason="Integration tests require --integration flag"
)然后,在测试文件中,这些装饰器可以被方便地应用于相关测试函数:
# test_something.py (Pytest 4.x 示例)
from .common import integration
@integration
def test_mytest():
assert 1 == 1
@integration
def test_other_mytest():
assert 2 == 2然而,从 Pytest 5.x+ 版本开始,pytest.config 属性已被移除,导致上述代码在运行时会抛出 AttributeError: module 'pytest' has no attribute 'config' 错误。对于那些拥有大量使用此类装饰器的现有测试的项目来说,如何在不进行大规模代码重构的前提下,在 Pytest 5.x+ 中实现相同的灵活性,成为了一个亟待解决的问题。
Pytest 5.x+ 提供了一种更简洁、更标准化的方式来解决这个问题,即通过自定义标记(Custom Markers)与内置的 -m 命令行选项。这种方法不仅能够实现与旧版 pytest.config 相同的功能,而且更加符合 Pytest 的设计哲学,并且对现有测试代码的改动极小。
首先,我们需要重新定义 integration 装饰器。在 Pytest 5.x+ 中,我们不再需要 pytest.config 来检查命令行选项,而是直接使用 pytest.mark 来创建标记。
# common.py (Pytest 5.x+ 解决方案) import pytest # 直接定义一个名为 'integration' 的标记 integration = pytest.mark.integration
然后,在测试文件中,继续使用这个新的 integration 装饰器来标记需要特殊处理的测试:
# test_skip.py (Pytest 5.x+ 解决方案)
from .common import integration
@integration
def test1():
assert True
def test2(): # 未被标记的测试
assert True为了让 Pytest 识别我们自定义的 integration 标记,并避免产生 PytestUnknownMarkWarning 警告,我们需要在项目根目录下的 pytest.ini 配置文件中注册它。
# pytest.ini [pytest] markers = integration: marks tests as integration tests (deselect with '-m "not integration"')
在 markers 部分,每行定义一个标记,冒号后可以添加对该标记的简短描述,这对于团队协作和文档化非常有帮助。
完成上述配置后,我们就可以利用 Pytest 的 -m 命令行选项来灵活地运行或跳过带有特定标记的测试了。
运行所有测试
不带任何标记筛选参数时,Pytest 将运行所有收集到的测试:
$ pytest -v ========================================= test session starts ========================================= platform linux -- Python 3.11.6, pytest-7.2.2, pluggy-1.0.0 -- /usr/bin/python3 cachedir: .pytest_cache rootdir: /home/lars/tmp/python, configfile: pytest.ini collected 2 items test_skip.py::test1 PASSED [ 50%] test_skip.py::test2 PASSED [100%] ========================================== 2 passed in 0.00s ==========================================
只运行带有 integration 标记的测试
使用 -m integration 选项,Pytest 将只选择并运行被 @integration 装饰器标记的测试:
$ pytest -v -m integration ========================================= test session starts ========================================= platform linux -- Python 3.11.6, pytest-7.2.2, pluggy-1.0.0 -- /usr/bin/python3 cachedir: .pytest_cache rootdir: /home/lars/tmp/python, configfile: pytest.ini collected 2 items / 1 deselected / 1 selected test_skip.py::test1 PASSED [100%] =================================== 1 passed, 1 deselected in 0.00s ===================================
只运行不带 integration 标记的测试
使用 -m 'not integration' 选项,可以运行所有未被 integration 标记的测试。注意 not integration 表达式需要用引号括起来,以避免 shell 解析问题。
$ pytest -v -m 'not integration' ========================================= test session starts ========================================= platform linux -- Python 3.11.6, pytest-7.2.2, pluggy-1.0.0 -- /usr/bin/python3 cachedir: .pytest_cache rootdir: /home/lars/tmp/python, configfile: pytest.ini collected 2 items / 1 deselected / 1 selected test_skip.py::test2 PASSED [100%] =================================== 1 passed, 1 deselected in 0.00s ===================================
从 Pytest 4.x 升级到 5.x+ 并解决 pytest.config 移除带来的条件测试执行问题,最优雅且推荐的方式是采用自定义标记结合 -m 命令行选项。通过简单的两步:重新定义装饰器为 pytest.mark.your_marker 并在 pytest.ini 中注册该标记,即可实现对测试的精细化控制。这种方法不仅解决了兼容性问题,还提升了测试管理的灵活性和可维护性,是 Pytest 升级过程中的一项重要实践。
以上就是Pytest 5.x+ 升级指南:通过自定义标记实现命令行条件测试运行与跳过的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号