一文带你深入理解python中pytest-repeat插件的工作原理

 更新时间:2023年09月02日 08:57:23   作者:郝同学的测开笔记  
这篇文章主要和大家一起深入探讨到底pytest_repeat插件的具体功能是如何实现的呢,相信具体了解了该插件,其他三方插件也可以很快了解它内部运行机制,所以本文详细讲解了python pytest-repeat插件的工作原理,需要的朋友可以参考下

不使用pytest_repeat插件如何实现重复执行用例

最笨的办法,当然是运行多次,但这显然不是我们需要的,我们知道装饰器可以在不修改原始代码的情况下,动态的增加功能或修改函数行为。显然,这里我们就可以使用装饰器来实现重复功能。

def repeat(nums: int = 2):
    def wrapper(func):
​
        @functools.wraps(func)
        def decorator(*args, **kwargs):
            for i in range(nums):
                func(*args, **kwargs)
​
        return decorator
​
    return wrapper

这段代码很好理解,定义了带有自定义参数的装饰器,表示装饰器内部函数执行的次数。这样在用例上使用@repeat()装饰器就可以达到用例重复运行的目的。但是统计结果仍然为1条用例。使用过pytest_repeat的同学知道它的统计结果是多条用例?那是如何做的呢,通过源码一探究竟。

pytest_repeat如何实现重复执行

源码直达

源码解读

def pytest_addoption(parser):
    parser.addoption(
        '--count',
        action='/pytest-dev/pytest-repeat/blob/v0.9.1/store',
        default=1,
        type=int,
        help='Number of times to repeat each test')
​
    parser.addoption(
        '--repeat-scope',
        action='/pytest-dev/pytest-repeat/blob/v0.9.1/store',
        default='function',
        type=str,
        choices=('function', 'class', 'module', 'session'),
        help='Scope for repeating tests')

这段代码定义了两个命令行选项:

  • --count:用于指定每个测试用例要重复执行的次数。action=store 表示将值存储在命令行参数中。
  • --repeat-scope:用于指定重复测试用例的作用域,可以选择 functionclassmodulesession。默认值是 functionaction=store 表示将值存储在命令行参数中。

这两个选项都是通过 parser.addoption 方法添加到 pytest 的命令行解析器中的。

当运行 pytest 并指定 --count--repeat-scope 参数时,pytest-repeat 插件将获取这些参数并自动为测试用例生成多个重复执行的实例。

例如,如果运行以下命令:

pytest --count=2 --repeat-scope=function

pytest-repeat 将会在执行 test_my_function 测试用例时,自动执行该测试用例两次。

action=storeargparse 模块中的一个参数,它指定了在命令行解析过程中如何处理选项的值。具体地说,action=store 表示将选项的值存储在命令行参数中。

当使用 parser.addoption 方法添加选项到命令行解析器时,通过指定 action=store,选项的值将被存储在解析结果中,可以通过相应的属性来获取这些值。

例如,当运行 pytest 命令时,指定的 --count--repeat-scope 选项的值会存储在命令行参数中。你可以使用 request.config.getoption 方法来获取这些存储的值,例如:

def test_example(request):
    count = request.config.getoption('--count') 
    # count = request.config.option.count 这样也能获取
    repeat_scope = request.config.getoption('--repeat-scope')
    # repeat_scope = request.config.option.repeat_scope
    # 使用获取到的值进行后续操作

在上面的示例代码中,使用 request.config.getoption 方法从命令行参数中获取了 --count--repeat-scope 的值,并分别存储在 countrepeat_scope 变量中。

总结:action=storeargparse 模块中的一个参数,用于指定将选项的值存储在命令行参数中。在 pytest 中,通过使用 request.config.getoption 方法可以获取存储在命令行参数中的选项值。

def pytest_configure(config):
    config.addinivalue_line(
        'markers',
        'repeat(n): run the given test function `n` times.')

这个函数在 pytest 的配置阶段被调用,通过调用 config.addinivalue_line() 将自定义标记 'repeat(n)' 添加到 pytest 的标记列表中。'repeat(n)' 标记可以用于指定一个测试函数需要重复运行的次数。

@pytest.fixture
def __pytest_repeat_step_number(request):
    marker = request.node.get_closest_marker("repeat")
    count = marker and marker.args[0] or request.config.option.count
    if count > 1:
        try:
            return request.param
        except AttributeError:
            if issubclass(request.cls, TestCase):
                warnings.warn(
                    "Repeating unittest class tests not supported")
            else:
                raise UnexpectedError(
                    "This call couldn't work with pytest-repeat. "
                    "Please consider raising an issue with your usage.")

这个 fixture 函数用于获取当前的重复运行步骤编号。它首先检查测试函数是否被 'repeat' 标记装饰,并从标记中获取重复次数。如果没有标记,则使用命令行参数中的 --count 参数作为默认值。

@pytest.hookimpl(trylast=True)
def pytest_generate_tests(metafunc):
    count = metafunc.config.option.count
    m = metafunc.definition.get_closest_marker('repeat')
    if m is not None:
        count = int(m.args[0])
    if count > 1:
        metafunc.fixturenames.append("__pytest_repeat_step_number")
​
        def make_progress_id(i, n=count):
            return '{0}-{1}'.format(i + 1, n)
​
        scope = metafunc.config.option.repeat_scope
        metafunc.parametrize(
            '__pytest_repeat_step_number',
            range(count),
            indirect=True,
            ids=make_progress_id,
            scope=scope
        )

这个 pytest_generate_tests 钩子函数会在 pytest 收集到所有测试函数之后被调用,并且它被设置为 trylast=True,以确保在其他钩子函数执行完毕之后再执行。

  • 首先,代码获取了 metafunc.config.option.count 的值,该值表示测试用例重复执行的次数。
  • 然后,代码调用 metafunc.definition.get_closest_marker('repeat') 来获取测试用例是否有被标记为 repeat 的 marker。
  • 如果有 repeat 的 marker 标记,则从 marker 中获取重复执行的次数,并将其赋值给 count 变量。
  • 接下来,代码通过 metafunc.fixturenames.append("__pytest_repeat_step_number") 添加了一个名为 __pytest_repeat_step_number 的 fixture 名称到 metafunc 的 fixture 列表中。
  • 之后,定义了一个辅助函数 make_progress_id,用于生成测试用例的进度标识符。
  • 根据 metafunc.config.option.repeat_scope 的值,确定了重复执行的作用域。
  • 最后,通过调用 metafunc.parametrize 来动态生成测试用例。它使用了 range(count) 来生成重复执行的步骤数量作为参数,并将 indirect=True 设置为在加载 fixture 时进行间接调用。同时,使用了之前定义的进度标识符生成函数和作用域来设置参数化的其他选项。

可以看到最终是通过参数化来实现的,这也就是为啥重复执行多次能当做多条用例。

最后

相信你看我之后依然有很多疑问,fixture是啥?mark是啥?参数request是啥?钩子函数是啥?parametrize参数化是啥?这些疑问可以先留着,这片内容我们主要讲了pytest_repeat具体实现逻辑,然后引出了这么多知识点,别着急,之后会一个个逐一消灭。

以上就是一文带你深入理解python中pytest-repeat插件的工作原理的详细内容,更多关于python pytest-repeat插件的资料请关注脚本之家其它相关文章!

相关文章

  • Python 实例进阶之预测房价走势

    Python 实例进阶之预测房价走势

    买房应该是大多数都会要面临的一个选择,当前经济和政策背景下,未来房价会涨还是跌?这是很多人都关心的一个话题。今天分享的这篇文章,以波士顿的房地产市场为例,根据低收入人群比例、老师学生数量等特征,利用 Python 进行了预测,给大家做一个参考
    2021-11-11
  • Pytest之测试命名规则的使用

    Pytest之测试命名规则的使用

    这篇文章主要介绍了Pytest之测试命名规则的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • 在Python中操作字典之clear()方法的使用

    在Python中操作字典之clear()方法的使用

    这篇文章主要介绍了在Python中操作字典之clear()方法的使用,是Python入门的基础知识,需要的朋友可以参考下
    2015-05-05
  • Python os模块学习笔记

    Python os模块学习笔记

    这篇文章主要介绍了Python os模块学习笔记,本文总结了OS模块的常用方法、实用方法,并给出了两个使用实例,需要的朋友可以参考下
    2015-06-06
  • Win10搭建Pyspark2.4.4+Pycharm开发环境的图文教程(亲测)

    Win10搭建Pyspark2.4.4+Pycharm开发环境的图文教程(亲测)

    本文主要介绍了Win10搭建Pyspark2.4.4+Pycharm开发环境的图文教程(亲测),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • Python线程问题与解决方案

    Python线程问题与解决方案

    在 Python 中,线程的使用可以有效提高程序的并发性和响应能力,尤其是在 I/O 密集型任务(如文件读写、网络请求)中,然而,线程在 Python 中也会引发一些常见问题,下面介绍 Python 线程问题的解决方案,需要的朋友可以参考下
    2024-09-09
  • Python使用Reflex构建现代Web应用的完全指南

    Python使用Reflex构建现代Web应用的完全指南

    这篇文章为大家深入介绍了Reflex框架的设计理念,技术特性,项目结构,核心 API,实际开发流程以及与其他框架的对比和部署建议,感兴趣的小伙伴可以了解下
    2025-05-05
  • python的virtualenv虚拟环境常见问题和命令

    python的virtualenv虚拟环境常见问题和命令

    在Python中,venv是一个用于创建和管理虚拟环境的模块,虚拟环境可以帮助你在项目之间隔离不同的Python包和依赖关系,这篇文章主要介绍了python的virtualenv虚拟环境常见问题和命令,需要的朋友可以参考下
    2024-07-07
  • 如何在Conda环境中降级Python版本详细指南

    如何在Conda环境中降级Python版本详细指南

    在Conda环境中查看Python版本是一个常见需求,特别是当您管理多个环境时,这篇文章主要介绍了如何在Conda环境中降级Python版本的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-11-11
  • Python 的 f-string 可以连接字符串与数字的原因解析

    Python 的 f-string 可以连接字符串与数字的原因解析

    这篇文章主要介绍了Python 的 f-string 可以连接字符串与数字的原因解析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02

最新评论