玩命加载中 . . .

pytest hook逐一详解


前言

从6月份下旬开始着手写,写到10月份,期间进行了多次的修正和调整。为了保持文章的连续性,决定从09-01开始按天释出文章。

文章总览

Initialization hooks called for every plugin

第一篇:pytest hook 之 pytest_addhooks

第二篇:pytest hook 之 pytest_plugin_registered

第三篇:pytest hook 之 pytest_addoption

第四篇:pytest hook 之 pytest_configure

Bootstrapping hooks called for plugins registered early enough

第五篇:pytest hook 之 pytest_cmdline_parse

第六篇:pytest hook 之 pytest_cmdline_preparse

第七篇:pytest hook 之 pytest_cmdline_main

第八篇:pytest hook 之 pytest_load_initial_conftests

collection hooks

第九篇:pytest hook 之 pytest_collection

第十篇:pytest hook 之 pytest_collection_modifyitems

第十一篇:pytest hook 之 pytest_collection_finish

第十二篇:pytest hook 之 pytest_ignore_collect

第十三篇:pytest hook 之 pytest_collect_file

第十四篇:pytest hook 之 pytest_collectstart

第十五篇:pytest hook 之 pytest_itemcollected

第十六篇:pytest hook 之 pytest_collectreport

第十七篇:pytest hook 之 pytest_deselected

第十八篇:pytest hook 之 pytest_make_collect_report

第十九篇:pytest hook 之 pytest_pycollect_makemodule

第二十篇:pytest hook 之 pytest_pycollect_makeitem

第二十一篇:pytest hook 之 pytest_pyfunc_call

第二十二篇:pytest hook 之 pytest_generate_tests

第二十三篇:pytest hook 之 pytest_make_parametrize_id

第二十四篇:pytest hook 之 pytest_runtestloop

第二十五篇:pytest hook 之 pytest_runtest_protocol

第二十六篇:pytest hook 之 pytest_runtest_logstart

第二十七篇:pytest hook 之 pytest_runtest_logfinish

第二十八篇:pytest hook 之 pytest_runtest_setup

第二十九篇:pytest hook 之 pytest_runtest_call

第三十篇:pytest hook 之 pytest_runtest_teardown

第三十一篇:pytest hook 之 pytest_runtest_makereport

第三十二篇:pytest hook 之 pytest_runtest_logreport

第三十三篇:pytest hook 之 pytest_report_to_serializable

第三十四篇:pytest hook 之 pytest_report_from_serializable

第三十五篇:pytest hook 之 pytest_fixture_setup

第三十六篇:pytest hook 之 pytest_fixture_post_finalizer

第三十七篇:pytest hook 之 pytest_sessionstart

第三十八篇:pytest hook 之 pytest_sessionfinish

第三十九篇:pytest hook 之 pytest_unconfigure

hooks for customizing the assert methods

第四十篇:pytest hook 之 pytest_assertrepr_compare

第四十一篇:pytest hook 之 pytest_assertion_pass

Hooks for influencing reporting (invoked from _pytest_terminal)

第四十二篇:pytest hook 之 pytest_report_header

第四十三篇:pytest hook 之 pytest_report_collectionfinish

第四十四篇:pytest hook 之 pytest_report_teststatus

第四十五篇:pytest hook 之 pytest_terminal_summary

第四十六篇:pytest hook 之 pytest_warning_recorded

Hooks for influencing skipping

第四十七篇:pytest hook 之 pytest_markeval_namespace

error handling and internal debugging hooks

第四十八篇:pytest hook 之 pytest_internalerror

第四十九篇:pytest hook 之 pytest_keyboard_interrupt

第五十篇:pytest hook 之 pytest_exception_interact

第五十一篇:pytest hook 之 pytest_enter_pdb

第五十二篇:pytest hook 之 pytest_leave_pdb

hook简介

pytest是一个强大的测试框架,它提供了一系列的hook函数,这些hook函数允许你在测试执行的不同阶段进行干预和扩展,以改变或增强测试的行为。

这些hook函数通常以pytest_为前缀,并在conftest.py文件或测试模块中定义。

如下图所示(点击图片可放大),在pytest用例执行过程中,每个过程都有钩子函数的参与:

列个大概的过程,如下图所示(点击图片可放大):

这篇文章是总览,我将逐一介绍pytest hook的使用方法。

pytest有哪些hook

pytest 8.0.2为例,它有如下hook函数:

root@Gavin:/usr/lib/python3/dist-packages/_pytest# cat hookspec.py | grep 'def pytest_' | awk -F '(' '{{print $1}}'
def pytest_addhooks
def pytest_plugin_registered
def pytest_addoption
def pytest_configure
def pytest_cmdline_parse
def pytest_cmdline_preparse
def pytest_cmdline_main
def pytest_load_initial_conftests
def pytest_collection
def pytest_collection_modifyitems
def pytest_collection_finish
def pytest_ignore_collect
def pytest_collect_file
def pytest_collectstart
def pytest_itemcollected
def pytest_collectreport
def pytest_deselected
def pytest_make_collect_report
def pytest_pycollect_makemodule
def pytest_pycollect_makeitem
def pytest_pyfunc_call
def pytest_generate_tests
def pytest_make_parametrize_id
def pytest_runtestloop
def pytest_runtest_protocol
def pytest_runtest_logstart
def pytest_runtest_logfinish
def pytest_runtest_setup
def pytest_runtest_call
def pytest_runtest_teardown
def pytest_runtest_makereport
def pytest_runtest_logreport
def pytest_report_to_serializable
def pytest_report_from_serializable
def pytest_fixture_setup
def pytest_fixture_post_finalizer
def pytest_sessionstart
def pytest_sessionfinish
def pytest_unconfigure
def pytest_assertrepr_compare
def pytest_assertion_pass
def pytest_report_header
def pytest_report_collectionfinish
def pytest_report_teststatus
def pytest_terminal_summary
def pytest_warning_recorded
def pytest_markeval_namespace
def pytest_internalerror
def pytest_keyboard_interrupt
def pytest_exception_interact
def pytest_enter_pdb
def pytest_leave_pdb
root@Gavin:/usr/lib/python3/dist-packages/_pytest# cat hookspec.py | grep 'def pytest_' | awk -F '(' '{{print $1}}' | wc -l
52
root@Gavin:/usr/lib/python3/dist-packages/_pytest#

pytest hook 分类

大致被分为以下几个阶段:初始化、配置、命令行处理、收集、运行测试、测试完成和清理等。下文按钩子的执行顺序与时机进行分类。

初始化阶段

   def pytest_addhooks(pluginmanager):
       # 注册新的插件钩子
       pass

   def pytest_plugin_registered(plugin, manager):
       # 每次注册插件后调用
       pass

配置阶段

   def pytest_addoption(parser, pluginmanager):
       # 添加命令行选项和ini配置文件值
       pass

   def pytest_configure(config):
       # 配置插件和初始化操作
       pass

命令行处理阶段

   def pytest_cmdline_parse(parser):
       # 解析命令行参数
       pass

   def pytest_cmdline_preparse(config, args):
       # 在默认和插件命令行参数解析之前预处理命令行
       pass

   def pytest_cmdline_main(config):
       # 处理测试运行的主要入口函数
       pass

初步加载阶段

   def pytest_load_initial_conftests(early_config, parser, args):
       # 最早加载conftest.py文件
       pass

收集阶段

   def pytest_collection(session):
       # 测试用例收集阶段
       pass

   def pytest_collection_modifyitems(session, config, items):
       # 修改收集的项,如重新排序或添加/移除项目
       pass

   def pytest_collection_finish(session):
       # 收集阶段结束
       pass

   def pytest_ignore_collect(path, config):
       # 决定是否忽略某个收集项目
       pass

   def pytest_collect_file(file_path, parent):
       # 收集文件
       pass

   def pytest_collectstart(collector):
       # 开始收集某个项目
       pass

   def pytest_collectreport(report):
       # 收集归档报告
       pass

   def pytest_make_collect_report(collector):
       # 创建收集报告
       pass

   def pytest_itemcollected(item):
       # 每收集到一个项目时调用
       pass

   def pytest_deselected(items):
       # 项目取消选择时调用
       pass

   def pytest_pycollect_makemodule(module_path, parent):
       # 创建一个模块收集器
       pass

   def pytest_pycollect_makeitem(collector, name, obj):
       # 创建收集项目
       pass

测试生成阶段


   def pytest_generate_tests(metafunc):
       # 动态生成测试用例
       pass

   def pytest_make_parametrize_id(config, val):
       # 用于生成参数化的测试标识符
       pass

运行测试阶段

   def pytest_runtestloop(session):
       # 测试运行循环
       pass

   def pytest_runtest_protocol(item, nextitem):
       # 运行单个测试项协议
       pass

   def pytest_runtest_logstart(nodeid, location):
       # 日志记录开始
       pass

   def pytest_runtest_logfinish(nodeid, location):
       # 日志记录结束
       pass

   def pytest_runtest_setup(item):
       # 测试项设置
       pass

   def pytest_pyfunc_call(pyfuncitem):
       # 实际调用测试函数
       pass

   def pytest_runtest_call(item):
       # 执行测试项
       pass

   def pytest_runtest_teardown(item, nextitem):
       # 清理测试项
       pass

   def pytest_runtest_makereport(item, call):
       # 制作测试报告
       pass

   def pytest_runtest_logreport(report):
       # 日志记录测试报告
       pass

   def pytest_report_to_serializable(report):
       # 报告序列化
       pass

   def pytest_report_from_serializable(config, data):
       # 从序列化数据中生成报告
       pass

fixture阶段

   def pytest_fixture_setup(fixturedef, request):
       # 设置fixture
       pass

   def pytest_fixture_post_finalizer(fixturedef, request):
       # fixture最终清理阶段后的操作
       pass

会话生命周期阶段

   def pytest_sessionstart(session):
       # 会话开始
       pass

   def pytest_sessionfinish(session, exitstatus):
       # 会话结束
       pass

   def pytest_unconfigure(config):
       # 解除配置并清理资源
       pass

断言阶段

    def pytest_assertrepr_compare(config, op, left, right):
        # 断言比较表示
        pass

    def pytest_assertion_pass(item, lineno, orig, expl):
        # 断言通过
        pass

报告阶段

    def pytest_report_header(config):
        # 报告前的头部信息
        pass

    def pytest_report_collectionfinish(config, startdir, items):
        # 收集结束时的报告信息
        pass

    def pytest_report_teststatus(report, config):
        # 测试状态的报告
        pass

    def pytest_terminal_summary(terminalreporter, exitstatus):
        # 终端汇总和总结
        pass

警告和内部错误、交互阶段


    def pytest_warning_recorded(warning_message, nodeid, location):
        # 记录警告
        pass

    def pytest_markeval_namespace(config):
        # 评估mark表达式的命名空间
        pass

    def pytest_internalerror(excrepr, excinfo):
        # 处理内部错误
        pass

    def pytest_keyboard_interrupt(excinfo):
        # 处理键盘中断
        pass

    def pytest_exception_interact(node, call, report):
        # 交互异常
        pass

    def pytest_enter_pdb(config, traceback, excinfo):
        # 进入PDB调试器
        pass

    def pytest_leave_pdb(config, traceback, excinfo):
        # 离开PDB调试器
        pass

钩子函数解释

  • pytest_addhooks: 在插件钩子系统注册新的钩子。

  • pytest_plugin_registered: 每次新插件注册时被调用。

  • pytest_addoption: 用于增加命令行参数和配置选项。

  • pytest_configure: 在测试运行开始时配置所有插件和初始化。

  • pytest_cmdline_parse: 解析命令行参数。

  • pytest_cmdline_preparse: 在命令行参数解析之前进行预处理。

  • pytest_cmdline_main: 处理测试运行的主要入口函数。

  • pytest_load_initial_conftests: 最早加载conftest.py文件。

  • pytest_collection: 表示开始收集测试用例。

  • pytest_collection_modifyitems: 修改或筛选已经收集的测试项。

  • pytest_collection_finish: 收集阶段结束时被调用。

  • pytest_ignore_collect: 决定是否忽略某个路径的收集。

  • pytest_collect_file: 收集指定文件中的测试项。

  • pytest_collectstart: 收集一个项目的开始阶段。

  • pytest_collectreport: 报告收集结果。

  • pytest_make_collect_report: 创建收集的报告对象。

  • pytest_itemcollected: 每收集到一个项目时被调用。

  • pytest_deselected: 某些项目被取消选择时被调用。

  • pytest_pycollect_makemodule: 创建模块收集器。

  • pytest_pycollect_makeitem: 创建具体的测试项。

  • pytest_generate_tests: 动态生成测试用例。

  • pytest_make_parametrize_id: 生成参数化测试用例的标识符。

  • pytest_runtestloop: 测试运行循环。

  • pytest_runtest_protocol: 运行单个测试项的协议。

  • pytest_runtest_logstart: 记录测试开始日志。

  • pytest_runtest_logfinish: 记录测试结束日志。

  • pytest_runtest_setup: 设置测试用例。

  • pytest_pyfunc_call: 实际调用测试函数。

  • pytest_runtest_call: 执行测试用例。

  • pytest_runtest_teardown: 清理测试用例。

  • pytest_runtest_makereport: 制作每个测试阶段的报告。

  • pytest_runtest_logreport: 记录测试报告日志。

  • pytest_report_to_serializable: 将报告对象转换为可序列化格式。

  • pytest_report_from_serializable: 从可序列化格式恢复报告对象。

  • pytest_fixture_setup: 设置fixture。

  • pytest_fixture_post_finalizer: fixture最终清理阶段后的操作。

  • pytest_sessionstart: 会话开始。

  • pytest_sessionfinish: 会话结束。

  • pytest_unconfigure: 解除配置并清理资源。

  • pytest_assertrepr_compare: 断言比较表示。

  • pytest_assertion_pass: 断言通过。

  • pytest_report_header: 报告前的头部信息。

  • pytest_report_collectionfinish: 收集结束时的报告信息。

  • pytest_report_teststatus: 测试状态的报告。

  • pytest_terminal_summary: 终端汇总和总结。

  • pytest_warning_recorded: 记录警告。

  • pytest_markeval_namespace: 评估mark表达式的命名空间。

  • pytest_internalerror: 处理内部错误。

  • pytest_keyboard_interrupt: 处理键盘中断。

  • pytest_exception_interact: 交互异常。

  • pytest_enter_pdb: 进入PDB调试器。

  • pytest_leave_pdb: 离开PDB调试器。

pytest Hooks 功能、使用场景和注意点

Hook 名称 功能描述 使用场景 注意点
pytest_addhooks 增加插件所需要的 hooks 用于自定义插件开发时增加新的 hooks 需要深刻理解 hooks 的管理机制
pytest_plugin_registered 插件被注册时调用 可用于记录插件的加载 确认插件注册逻辑无循环引用
pytest_addoption 增加自定义命令行选项 用于提供额外的命令行参数 确保命令行参数的名称和描述具有唯一性
pytest_configure 在会话配置时调用 用于配置初始化,设置全局变量 必须在 pytest_sessionstart 前调用
pytest_cmdline_parse 命令行解析完成后调用 用于在命令行参数解析后添加自定义逻辑 解析逻辑应兼容所有合法命令行参数
pytest_cmdline_preparse 命令行初始解析之前调用 可在参数解析之前进行预处理 避免破坏命令行标准参数
pytest_cmdline_main 主命令行解析后立即调用 可对最终命令行参数进行调整 确保调整的参数能被预期的函数识别
pytest_load_initial_conftests 装载初始 conftest.py 文件 用于初始化 conftest.py 配置文件 确保 conftest.py 文件路径及加载顺序正确
pytest_collection 开始收集测试项目调用 用于收集测试用例前的准备工作 确保收集逻辑无副作用
pytest_collection_modifyitems 收集到测试项目后调用可修改测试集合 用于动态过滤、排序测试用例 确保修改测试集合的逻辑无副作用
pytest_collection_finish 收集测试项目完成后调用 收集完成后的清理和日志记录 确保收集完成的状态一致
pytest_ignore_collect 某个路径被忽略时调用 用于过滤掉不需要的测试文件 确保过滤路径完全覆盖所需范围
pytest_collect_file 收集文件时调用 用于自定义文件收集逻辑 确保路径处理符合预期
pytest_collectstart 开始收集某个项目时调用 可用于在特定目录或模块开始时的初始化工作 防止无限循环收集
pytest_itemcollected 每个测试项目被收集到时调用 用于记录收集到的测试用例 在收集项目时避免耗时操作
pytest_collectreport 收集报告生成时调用 用于处理收集报告 确保报告生成逻辑与期望一致
pytest_deselected 测试项目被过滤掉时调用 用于记录被过滤掉的测试项目 防止误删关键测试用例
pytest_make_collect_report 创建收集报告时调用 用于生成自定义收集报告 确保报告内容充分反映收集过程
pytest_pycollect_makemodule 创建 Python 模块收集项目 用于自定义模块收集逻辑 确保模块的合法性
pytest_pycollect_makeitem 创建 Python 测试项目 用于自定义测试项目的创建逻辑 确保项目收集逻辑满足预期
pytest_pyfunc_call 调用测试函数时调用 用于自定义测试函数调用行为 确保调用逻辑没有副作用
pytest_generate_tests 动态生成测试用例 用于参数化测试生成测试用例 确保生成的测试用例符合命名规则
pytest_make_parametrize_id 生成参数化的 id 用于生成更具可读性的参数化 id 保证参数化 id 的唯一性
pytest_runtestloop 测试运行主循环 用于修改或增强测试运行循环 确保自定义逻辑不破坏测试流程
pytest_runtest_protocol 每个测试用例的运行协议 用于控制单个测试用例的运行过程 确保测试运行协议的完整性
pytest_runtest_logstart 每个测试用例开始时的日志记录 用于记录测试用例开始执行信息 确保日志格式与系统一致
pytest_runtest_logfinish 每个测试用例结束时的日志记录 用于记录测试用例结束执行信息 确保结束日志与开始日志匹配
pytest_runtest_setup 测试用例运行前 用于测试环境的准备工作 确保所有前置条件都已配置完毕
pytest_runtest_call 测试用例运行时调用 用于自定义测试用例运行逻辑 确保运行逻辑没有副作用
pytest_runtest_teardown 测试结束后的清理工作 用于清理测试环境以及资源回收 确保清理确实完成且无副作用
pytest_runtest_makereport 生成测试用例的运行报告 用于生成自定义测试报告 确保报告内容准确反映测试结果
pytest_runtest_logreport 测试用例完成时的日志记录 用于记录测试用例的最终状态 确保日志详细记录测试结果
pytest_report_to_serializable 将报告对象序列化 用于报告多进程、多主机环境下的传输 确保序列化格式的一致性
pytest_report_from_serializable 从序列化对象还原报告 用于报告多进程、多主机环境下的还原 确保反序列化格式的一致性
pytest_fixture_setup 固件被设置时调用 用于自定义固件设置逻辑 确保固件设置无副作用
pytest_fixture_post_finalizer 固件最后一个 finalizer 运行后调用 用于自定义固件后处理逻辑 确保固件后处理无副作用
pytest_sessionstart 测试会话启动时调用 用于初始化测试会话 确保会话启动逻辑的唯一性
pytest_sessionfinish 测试会话结束时调用 用于清理测试会话资源 确保所有资源都已被正确释放
pytest_unconfigure 测试会话完全结束时调用 用于配置文件和内存的最终清理 确保所有配置和内存都已被正确清理
pytest_assertrepr_compare 断言比较时调用 用于自定义断言比较信息 确保断言信息的详细和准确
pytest_assertion_pass 当断言通过时调用 用于记录成功断言的日志 可以选择性记录成功断言
pytest_report_header 生成测试报告的头部信息 用于自定义测试报告头部 确保头部信息的清晰和准确
pytest_report_collectionfinish 在测试集合完成后生成报告头部信息 增强报告内容,确保收集过程的完整性 确保报告准确反映测试集合的实际状态
pytest_report_teststatus 修改或增加测试状态信息 自定义测试状态,以更好地符合项目需求 确保测试状态与实际一致,避免误导
pytest_terminal_summary 生成测试会话的最终总结报告 统一输出测试结果,提供整体视图 确保报告内容的全面和准确
pytest_warning_recorded 记录测试中出现的警告信息 收集、记录或处理测试警告 确保警告信息的完整记录,避免遗漏重要警告
pytest_markeval_namespace 自定义标记表达式解析命名空间 定义新的标记规则和解析逻辑 确保新规则符合项目的实际需求
pytest_internalerror 捕获 pytest 框架自身的内部错误 记录和处理 pytest 内部错误 捕获到内部错误时,确保不会影响其他测试流程
pytest_keyboard_interrupt 处理键盘中断事件 可用于处理 Ctrl+C 中断并进行善后处理 确保中断事件处理不影响已完成的测试结果
pytest_exception_interact 在测试过程中抛出异常时与之交互 捕获测试中异常,提供交互式调试或日志记录 确保异常信息的详细记录,便于后续分析处理
pytest_enter_pdb 进入 pdb 调试模式时调用 预设调试环境,打印调试信息 确保调试信息的详细和准确,可以有效指导问题定位
pytest_leave_pdb 离开 pdb 调试模式时调用 清理调试状态,记录调试结束信息 确保调试状态的清理正确,避免影响后续测试

文章作者: Gavin Wang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Gavin Wang !
 上一篇
自己总结的《pytest测试指南》一书,800余页 自己总结的《pytest测试指南》一书,800余页
历经十八个月的辛勤耕耘,一部800余页的《pytest测试指南》完稿。本书不仅提供了pytest的全面介绍,更深入细致地探讨了具体的API项目实践。此外,书中还详尽阐述了如何将pytest与Jenkins相结合,以实现持续集成(CI)的完美落地。这是一部从基础入门到实际项目应用的完整手册,每一页、每一章节都凝聚心血、精心雕琢。对于渴望深入掌握pytest的读者而言,本书无疑是一份不可多得的宝贵资源,值得细细品读。
下一篇 
博客RRS订阅出现XML内容 博客RRS订阅出现XML内容
博客进行RRS订阅时,出现XML内容的解决方案
2999-12-29
  目录