Pytest精通指南(21)钩子函数-失败重试(pytest-rerunfailures)

46 篇文章 1 订阅
28 篇文章 1 订阅


在这里插入图片描述

前言

  • pytest是一个功能强大的自动化测试框架,它提供了丰富的命令行选项和配置,能够满足多种测试需求。

  • 不仅如此,pytest还可以通过插件机制进一步扩展了其功能。

  • 插件的定制和开发都离不开钩子函数(hook functions),因为它们是pytest框架中实现扩展的关键。

  • 通过钩子函数,我们可以轻松地定制和扩展pytest的行为,以满足更具体、更复杂的测试场景。

钩子函数的简介

  • 想象一下我们正在参加一个晚会,而pytest就是这个晚会的组织者。

  • 在晚会的不同阶段,如入场、就餐、表演、离场等,都有一些固定的活动和流程。

  • 但是,pytest(组织者)也想给参与者提供一些展示自我的机会,比如允许我们在特定的时间点播放自己准备的音乐、进行特别的表演等。

  • 这些特定的时间点,在pytest中,就是所谓的“钩子”。

  • 它们是晚会流程中预定的位置,组织者知道在这个时间点会有活动发生,但具体的活动内容是可以自定义的,而“钩子函数”,就是参与者为这些钩子提供的具体活动内容。


简而言之:

  • pytest框架中,钩子函数(Hook Functions)是一种特殊的函数,它们允许我们在pytest的内部处理流程中特定的点插入自定义的行为。

  • 这些特定的点被称为“钩子”(Hooks),它们定义在pytest的内部,而我们可以通过实现相应的钩子函数来定制pytest的行为。

请添加图片描述

钩子函数的作用

  • 扩展功能:钩子函数允许我们扩展pytest的功能,添加额外的行为或修改默认的行为。
  • 定制流程:可以通过钩子函数在测试执行的不同阶段定制流程,例如测试准备、测试执行、测试结果处理等。
  • 集成第三方工具:钩子函数可以用于集成第三方工具或库,与pytest的测试流程相结合,提供更丰富的功能和更灵活的处理方式。

钩子函数的加载

  • 内置插件pytest自带了一些内置插件,这些插件为pytest提供了核心功能。它们通常位于_pytest目录中,这是pytest的内部包,包含了框架的核心实现和插件
  • 第三方插件:可以通过setuptoolsentry_points机制来注册和发现。当你在setup.py文件中为你的插件定义了一个pytest入口点时,pytest就能够在运行时发现并加载它。
  • 本地插件conftest.py文件是一种特殊的本地插件,pytest会在其目录树中自动发现并加载它们。这些文件可以包含pytest的钩子函数、fixture和其他配置。

钩子函数的分类

pytest有非常多的插件,居pypi统计目前已高达1400+

官网地址:https://docs.pytest.org/en/latest/reference/plugin_list.html#plugin-list


如果我们按照测试执行的流程来划分钩子的位置,可以大致分为以下几个阶段(不完全统计):

初始化与配置阶段

  • pytest_cmdline_main: 当从命令行运行pytest时被调用,是pytest的主入口点。

  • pytest_configure: pytest配置阶段调用,用于设置测试环境。

  • pytest_plugin_registered: 当pytest插件注册时调用。

  • pytest_report_header: 用于生成测试报告时的自定义标题。

  • pytest_addoption:用于向pytest的命令行解析器添加自定义选项。

  • pytest_sessionstart: 整个测试会话开始时调用。

用例收集阶段

  • pytest_collect_file: 收集单个文件作为测试模块时调用。
  • pytest_collect_directory: 收集目录作为测试模块时调用。
  • pytest_collect_module: 收集Python模块作为测试模块时调用。
  • pytest_collect_item: 收集单个测试项(如函数、方法或类)时调用。
  • pytest_generate_tests: 生成测试用例时调用,常用于参数化。
  • pytest_make_parametrize_id: 为参数化测试生成ID时调用。
  • pytest_collection_modifyitems: 修改已收集的测试用例项时调用。
  • pytest_collection_finish: 用例收集阶段结束时调用。

用例准备与执行阶段

  • pytest_runtest_protocol: 开始执行单个测试项之前调用,用于设置执行协议。
  • pytest_runtest_setup: 在执行测试项之前设置fixture和其他准备工作时调用。
  • pytest_runtest_call: 实际执行测试项(如函数或方法)时调用。
  • pytest_runtest_teardown: 在测试项执行完毕后进行清理时调用。
  • pytest_runtest_logstart: 用于开始测试项的日志记录。
  • pytest_runtest_logfinish: 用于结束测试项的日志记录。

报告与总结阶段

  • pytest_make_collect_report: 生成收集阶段的测试报告。
  • pytest_collectreport: 生成收集阶段的测试报告。
  • pytest_make_test_report: 生成测试项的执行报告.
  • pytest_runtest_makereport: 生成测试项的执行报告。
  • pytest_report_teststatus: 报告单个测试项的状态时调用。
  • pytest_terminal_summary: 在终端显示测试总结信息时调用。
  • pytest_sessionfinish: 整个测试会话结束时调用。

异常与调试阶段

  • pytest_exception_interact: 当未捕获的异常导致测试失败时,允许用户交互地调试。
  • pytest_internalerror: 当pytest遇到内部错误时调用。

清理与卸载阶段

  • pytest_unconfigure: 在pytest配置清理阶段调用,用于清理测试环境。

第一个钩子函数-失败重跑

  • 作用说明pytest失败重跑插件可以在测试用例执行失败后进行重新执行,以提高测试的可靠性和稳定性。
  • 应用场景:当服务器不稳定、网络波动等导致用例执行失败时,可以使用该插件进行失败重跑,以避免因偶然因素导致的测试失败。
  • 使用规则:需要安装pytest-rerunfailures插件,并在pytest命令行中添加相应的参数来指定重跑的次数和延时时间等。

插件安装

安装命令pip install pytest-rerunfailures

请添加图片描述

使用方式一:命令行

作用域:全局

命令行参数:

  • --reruns n:这个参数用于指定一个测试用例失败后最多重跑的次数。n 是一个正整数,表示重跑的次数。这是一个必填参数。
  • --reruns-delay m:这个参数用于指定两次重跑之间的延迟时间(以秒为单位)。m 是一个正整数,表示延迟的秒数。这是一个可选参数。
  • 命令示例pytest --reruns 3 --reruns-delay 1

示例代码

def test_case_01():
    assert 1 == 1, "断言失败"


def test_case_02():
    assert 1 == 2, "断言失败"

执行结果

请添加图片描述

使用方式二:配置文件

作用域:全局

功能描述:可以在 pytest.ini 配置文件中设置这些参数,这样就不需要在每次运行测试时都指定它们了。

注意说明addopts 配置项中的 -vs 是额外的选项,用于启用详细输出(-v 表示详细输出,s 表示显示捕获的输出)。

这些并不是 pytest-rerunfailures 插件必需的,而是用于演示如何在 addopts 中添加多个选项。


pytest.ini配置文件添加如下

[pytest]
addopts = -vs --reruns=2 --reruns-delay=1

示例代码

def test_case_01():
    assert 1 == 1, "断言失败"


def test_case_02():
    assert 1 == 2, "断言失败"

执行结果

请添加图片描述

使用方式三:装饰器

作用域:局部
功能描述@pytest.mark.flaky(reruns=m, reruns_delay=n) 是一个pytest的装饰器,用于标记那些可能会偶尔失败但通常能够成功通过的测试用例。当使用此装饰器时,如果标记的测试用例失败,pytest会尝试重新运行该用例指定的次数。

参数含义

  • reruns=m:指定如果测试用例失败,应重新运行的次数。m 是一个整数,表示重跑的次数。
  • reruns_delay=n:指定每次重跑之间的延迟时间(以秒为单位)。n 是一个整数,表示每次重跑前等待的秒数。

示例代码

import pytest


def test_case_01():
    assert 1 == 1, "断言失败"


@pytest.mark.flaky(reruns=3, reruns_delay=1)
def test_case_02():
    assert 1 == 2, "断言失败"

执行结果

请添加图片描述

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

需要休息的KK.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值