pytest测试框架之插件(hook函数)开发

本文详细介绍了pytest测试框架中的hook函数,特别是pytest_collection_modifyitems的功能,用于在测试用例收集阶段修改编码和执行顺序。通过conftest.py中的hook函数实现自定义测试行为,包括处理编码问题和生成XML报告中的用例ID。
摘要由CSDN通过智能技术生成

pytest测试框架之插件(hook函数)开发

参考文档:
https://docs.pytest.org/en/7.1.x/how-to/writing_hook_functions.html
https://juejin.cn/post/7281080420379131958
https://zhuanlan.zhihu.com/p/610804545

pytest 三种插件

pytest 给我们开放了大量的 hook 函数,可以编写插件。pytest 三种插件类型:

  1. 内置插件:从 pytest 内部 _pytest 目录加载的插件
  2. 外部插件:通过 pip 安装的插件(比如: pip install pytest-ordering )
  3. conftest.py 插件:测试目录中的 conftest.py 加载

pytest hook 函数

pytest hook 链接: https://docs.pytest.org/en/stable/reference.html?#hooks
pytest hook 函数也叫钩子函数,pytest 提供了大量的钩子函数,可以在用例的不同生命周期自动调用。 比如,在测试用例收集阶段,可利用 hook 函数修改测试用例名称的编码。
通常我们会把 hook 函数编写在项目的 conftest.py 文件中:

def pytest_collection_modifyitems(
 session: "Session", config: "Config", items: List["Item"]
) -> None:
 for item in items:
 item.name = item.name.encode('utf-8').decode('unicode-escape')
 item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')

运行时,pytest 会优先加载 conftest.py 文件,然后再执行测试用例,这个 hook 函数 pytest_collection_modifyitems 是负责修改收集上来的测试用例的,也就是我们可以将收集上来的 测试用例重新改写它的编码规范,当然也可以修改它的执行顺序。下面我们来看一下 pytest 提供了哪些 hook 函数。

pytest hook函数及执行顺序

pytest 提供了大量的 hook 函数,执行过程中几乎所有的行为都是可以定制的。文字版 pytest hook 执行顺序:

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_collection_modifyitems

运行测试用例的时候,可能会遇到编码的问题,比如路径里有中文,展示的时候,可能会出现乱码。

需求&源码分析

从源码 site_packages/_pytest/hookspec.py 中(ubuntu18系统通常位置在家目录./lib/python3.6/site-packages/_pytest/hookspec.py)查看 pytest_collection_modifyitems hook函 数的源码:

def pytest_collection_modifyitems(session, config, items):
 """ called after collection has been performed, may filter or re-order
 the items in-place.
 :param _pytest.main.Session session: the pytest session object
 :param _pytest.config.Config config: pytest config object
 :param List[_pytest.nodes.Item] items: list of item objects
 """

该函数是在用例收集完毕之后被调用,可以过滤或者调整测试用例执行顺序。 里面需要传递三个参数,其中 items 是测试的用例对象列表。可以通过遍历 items,然后对每个测试用例的名字重新编码,实现改写编码的效果。

item常用属性

item.nodeid: 返回一个字符串,表示测试用例的唯一标识符。
item.name: 返回一个字符串,表示测试用例的名称。
item.parent: 返回一个节点对象,表示测试用例所属的父级节点(模块、类或测试集合)。
item.function: 返回一个函数对象,表示测试用例的实际执行函数。
item.originalname: 返回一个字符串,表示测试用例的原始名称。
item.location: 返回一个元组,包含测试用例所在文件的路径和行号。
item.keywords:返回一个包含字符串关键字的集合

hook函数本文件夹下生效

创建目录结构如下:
pytest-changcode
├── pytest_changecode
│ └── init.py
└── tests
└── test_code.py
创建插件包 pytest_changecode ,创建测试包 tests
在 tests/test_code.py 文件中添加测试代码,如下:

@pytest.mark.parametrize("name",["张三","李四"])
def test_encode(name):
 print(name)

在pytest_changecode/init.py 文件中添加改写编码的内容,代码如下:

def pytest_collection_modifyitems(items):
for item in items:
item.name = item.name.encode(‘utf-8’).decode(‘unicode_escape’)
item._nodeid = item._nodeid.encode(‘utf-8’).decode(‘unicode_escape’)

hook函数全局生效

把 hook 函数编写在项目的 conftest.py 文件中

def pytest_collection_modifyitems(
 session: "Session", config: "Config", items: List["Item"]
) -> None:
 for item in items:
 item.name = item.name.encode('utf-8').decode('unicode-escape')
 item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')

运行机制总结

pytest_collection_modifyitems()钩子函数的运行机制如下:

在 Pytest 运行过程中,当测试集被收集完成后,Pytest 会检测到conftest.py文件中是否定义了 pytest_collection_modifyitems() 函数。
如果 conftest.py中定义了 pytest_collection_modifyitems() 函数,Pytest 会调用该函数,并传递两个参数:config 和 items。config 参数是一个对象,包含了当前测试运行的配置信息。我们可以使用它来访问和修改配置选项,或者获取有关测试环境和命令行参数的信息。
items 参数是一个列表,其中包含了所有收集到的测试项对象。每个测试项对象都包含了测试项的相关信息,如名称、路径、函数/方法定义等。
在 pytest_collection_modifyitems() 函数内部,我们可以根据需要对 items 列表进行修改。例如,重新排序测试项、过滤测试项、添加标记等。修改 items 列表后,Pytest 将按更新后的顺序和配置继续执行测试。修改后的 items 列表中包含了经过钩子函数处理后的测试项。

总结来说,pytest_collection_modifyitems() 钩子函数在测试集被收集之后被调用,允许我们对收集到的测试项进行自定义修改。通过使用该钩子函数,我们可以根据特定需求实现对测试项的排序、过滤、标记等操作,从而更好地管理和执行测试。

拓展:添加用例id用于生成xml报告

def pytest_collection_modifyitems(items):
	for item in items:
	    case_id = item.name
	    case_id = case_id.split("[")[-1].split("]")[0].split("-")[-1]
	    if case_id.isdigit():
	        item.user_properties.append(("id", case_id))

item.user_properties是一个可供用户自定义使用的变量。在这里插入图片描述

  • 21
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值