本文共 5195 字,大约阅读时间需要 17 分钟。
Pytest测试框架功能强大,它实际上是由一系列插件构成的,提供了丰富的定制化选项,能够满足大多数测试需求。本文将详细介绍Pytest插件的开发方法,帮助您更好地理解Pytest测试框架。
Pytest插件主要分为三种类型:
_pytest 中,主要包括 hookspec.py 文件。pip install 安装,利用 setuptools 的 Entry points 机制发现这些插件。常见的外部插件有 pytest-ordering 和 pluggy。conftest.py 文件,作为全局插件使用;而在项目子目录中的 conftest.py 文件,其作用范围仅限于该层级及以下目录。插件的加载顺序为:内置插件 → 外部插件 → 本地插件。
Pytest钩子函数(Hook Functions)是预留的函数,用于在特定步骤执行自定义操作。通过重写特定的钩子函数,您可以为Pytest框架添加功能。例如,您可以重写 pytest_collection_modifyitems 钩子函数来对测试用例进行过滤或重新排序。
Pytest钩子的执行顺序如下:
root├── pytest_cmdline_main│ ├── pytest_plugin_registered│ ├── pytest_configure│ │ └── pytest_plugin_registered│ ├── pytest_sessionstart│ │ ├── pytest_plugin_registered│ │ └── pytest_report_header│ ├── pytest_collection│ │ ├── pytest_collectstart│ │ ├── pytest_make_collect_report│ │ │ ├── pytest_collect_file│ │ │ │ └── pytest_pycollect_makemodule│ │ │ │ └── pytest_pycollect_makeitem│ │ │ │ └── pytest_generate_tests│ │ │ └── pytest_make_parametrize_id│ │ ├── pytest_collectreport│ │ ├── pytest_itemcollected│ │ ├── pytest_collection_modifyitems│ │ └── pytest_collection_finish│ │ └── pytest_report_collectionfinish│ ├── pytest_runtestloop│ │ └── pytest_runtest_protocol│ │ ├── pytest_runtest_logstart│ │ ├── pytest_runtest_setup│ │ │ └── pytest_fixture_setup│ │ ├── pytest_runtest_makereport│ │ ├── pytest_runtest_logreport│ │ │ └── pytest_report_teststatus│ │ ├── pytest_runtest_call│ │ │ └── pytest_pyfunc_call│ │ ├── pytest_runtest_teardown│ │ │ └── pytest_fixture_post_finalizer│ │ └── pytest_runtest_logfinish│ ├── pytest_sessionfinish│ │ └── pytest_terminal_summary└── pytest_unconfigure
通过修改这些钩子函数,您可以添加自定义功能。例如,pytest_generate_tests 和 pytest_sessionstart 钩子函数的实现可以在 fixtures.py 文件中找到。
Pytest插件的管理和调用的核心是 pluggy 系统。pluggy 的作用是实现主程序与插件之间的连接,使得插件能够通过钩子函数与Pytest集成。
要为Pytest添加命令行参数,可以通过重写 pytest_addoption 钩子函数。例如,在 conftest.py 中添加以下代码:
def pytest_addoption(parser, pluginmanager): mygroup = parser.getgroup("testgroup") mygroup.addoption("--env", default='test', dest='env', help='设置运行环境') 然后在命令行中使用 --env 参数,如:
pytest -h
帮助信息中应显示新的参数选项:
testgroup: --env=ENV 设置运行环境
在 conftest.py 中添加 fixture:
@pytest.fixture(scope='session')def cmdoption(request): env = request.config.getoption("--env", default='test') if env == "test": print("测试环境") datapath = "data/test/data.yml" if env == "develop": print("开发环境") datapath = "data/develop/data.yml" with open(datapath) as f: datas = yaml.safe_load(f) return env, datas 编写测试用例:
def test_env(cmdoption): env, datas = cmdoption host = datas['env']['host'] port = datas['env']['port'] url = f"{host}:{port}" print(url) 运行测试用例:
pytest -vs test_hook.py::test_env
结果应显示测试环境信息:
test_hook.py::test_env 测试环境http://192.168.11.1:4567
通过命令行传递环境参数:
pytest -vs --env develop test_hook.py::test_env
结果应显示开发环境信息:
test_hook.py::test_env 开发环境http://192.168.0.1:1234
完成插件开发后,可以通过以下步骤进行打包和发布:
创建包文件
创建 setup.py 脚本:
from setuptools import setup, find_packagessetup( name="pytest-encode", version="0.0.1", author="hiyongz", author_email="zhiyo2016@163.com", description="设置编码", long_description="Pytest编码插件文档", url="https://github.com/pypa/sampleproject", project_urls={ "Bug Tracker": "https://github.com/pypa/sampleproject/issues", }, classifiers=[ "Programming Language :: Python :: 3", "Framework :: Pytest", "Topic :: Software Development :: Testing", ], license='MIT License', packages=find_packages('pytest_encode'), install_requires=[ 'pytest', ], python_requires=">=3.6", entry_points={ 'pytest11': [ 'pytest-encode = pytest_encode', ], }, zip_safe=False,) 依赖项保存至 requirements.txt:
pip freeze > requirements.txt
打包
在包目录中执行:
python setup.py sdist bdist_wheel
生成文件如下:
pytest-encode/├── build/│ └── bdist.win-amd64/│ └── lib/│ └── pytest_encode/│ └── __init__.py├── dist/│ └── pytest-encode-0.0.1.tar.gz└── pytest_encode-0.0.1-py3-none-any.whl └── pytest_encode.egg-info/ ├── dependency_links.txt ├── entry_points.txt ├── not-zip-safe ├── PKG-INFO ├── requires.txt ├── SOURCES.txt └── test_encode.py
测试打包文件
创建虚拟环境并安装包:
pip install pytest_encode-0.0.1-py3-none-any.whl
编写测试用例:
import pytestfrom pytest_encode import logger@pytest.mark.parametrize("name", ["张三", "李四"])def test_name(name): logger.info("测试编码") print(name) 运行测试用例:
pytest -vs test_encode.py::test_name
结果应显示中文名称:
test_encode.py::test_name 李四test_encode.py::test_name 张三
发布包
使用 twine 将包发布到 PyPI:
twine upload --repository test-encode dist/*
上传成功后,您可以在 PyPI 网站查看包详情。
pytest-ordering 插件pluggy 插件Pytest插件开发是通过钩子函数实现的,通过重写这些钩子函数,可以为Pytest框架添加各种功能。本文通过实际案例展示了如何开发和利用Pytest插件,包括中文编码、添加命令行参数、打包发布等内容。希望本文能为您提供Pytest插件开发的实用指导。
转载地址:http://axouz.baihongyu.com/