pytest-xdist分布式测试原理浅析

这篇具有很好参考价值的文章主要介绍了pytest-xdist分布式测试原理浅析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

pytest-xdist执行流程:

pytest-xdist 模块结构:

pytest-xdist分布式测试原理:

pytest-xdist源码浅读:


pytest-xdist执行流程:

  1. 解析命令行参数:pytest-xdist 会解析命令行参数,获取用户指定的分发模式、进程数、主机列表等信息。

  2. 加载测试用例:pytest-xdist 会加载所有的 pytest 测试用例,包括在当前目录和子目录下的所有测试文件和测试函数。

  3. 分发测试用例:根据用户指定的分发模式,pytest-xdist 会将测试用例分发到多个进程或主机上执行。如果是分发到多个进程,pytest-xdist 会创建多个子进程,每个子进程都会执行一部分测试用例。如果是分发到多个主机,pytest-xdist 会在每个主机上启动一个 Python 进程,然后将测试用例分发给每个 Python 进程执行。

  4. 执行测试用例:在每个进程或主机上,pytest-xdist 会执行分配给它的测试用例。每个进程或主机上的测试执行都是独立的,它们之间没有任何数据共享或通信。

  5. 汇总测试结果:在所有进程或主机上的测试执行完成后,pytest-xdist 会将所有测试结果汇总到主进程中,并输出测试报告。在汇总测试结果的过程中,pytest-xdist 还会根据用户指定的选项合并相同的测试结果,比如合并多个进程或主机上的相同测试用例结果。

  6. 清理资源:在所有测试结果都汇总完成后,pytest-xdist 会清理所有的资源,包括关闭分配给每个进程或主机的 Python 进程、删除临时文件等。

需要注意的是,pytest-xdist 的执行流程是一个异步的过程,不同进程或主机上的测试执行是并行的,它们之间没有任何阻塞或等待

pytest-xdist 模块结构:

  1. xdist 模块:这是 pytest-xdist 的主模块,包含了分发测试用例的主要逻辑。在 xdist 模块中,主要包含了以下几个子模块:

    • looponfail: 在测试用例执行失败时自动重试的逻辑。
    • loadfile: 加载分布式测试配置文件的逻辑。
    • rsync: 在多个主机之间同步文件的逻辑。
    • newhooks: 扩展 pytest 的钩子函数以支持分布式测试的逻辑。
  2. testing 模块:这是 pytest-xdist 的测试模块,包含了对 pytest-xdist 的单元测试和集成测试。

  3. docs 模块:这是 pytest-xdist 的文档模块,包含了 pytest-xdist 的文档说明和示例代码。

pytest-xdist分布式测试原理:

pytest-xdist 的核心原理是使用 py.execnet 这个 Python 库,它是一个用于远程执行 Python 代码的库。pytest-xdist 利用 py.execnet 提供的功能,将测试用例分发到多个进程或主机上执行,然后将结果汇总返回给主进程。

具体来说,pytest-xdist 在执行 pytest 测试用例时,会根据用户指定的分发模式(如 --numprocesses 或者 --tx),将测试用例分发到多个进程或者多个主机上。对于分发到多个进程的情况,pytest-xdist 会创建多个子进程,每个子进程都会执行一部分测试用例。对于分发到多个主机的情况,pytest-xdist 利用 py.execnet 在每个主机上启动一个 Python 进程,然后将测试用例分发给每个 Python 进程执行。

在测试用例执行完成后,pytest-xdist 会将所有测试结果汇总到主进程中,并输出测试报告。此外,pytest-xdist 还提供了一些功能,如在多个进程或主机之间共享数据、控制测试用例的执行顺序等。

总的来说,pytest-xdist 利用 py.execnet 提供的远程执行 Python 代码的功能,将 pytest 测试用例分发到多个进程或主机上执行,从而实现了测试用例的并行执行,提高了测试效率。

pytest-xdist源码浅读:

解析命令行参数

pytest-xdist 首先会解析命令行参数,从而获取用户指定的分发模式、进程数、主机列表等信息。这个过程是通过 pytest_addoption 钩子函数来实现的,它会在 pytest 启动时被调用,从而向 pytest 注册新的命令行选项。这里是相关的源码:

def pytest_addoption(parser):
    group = parser.getgroup("xdist", "distributed and subprocess testing")
    group._addoption(
        "-n",
        "--numprocesses",
        dest="numprocesses",
        type=int,
        default=None,
        help="shortcut for '--dist=load --tx=NUM*popen//python=python%s' (default: %default)" % sys.version_info[0],
    )
    group._addoption(
        "--tx",
        dest="tx",
        metavar="xspec",
        help="addrs[:spec] of test exec environments to use, "
        "see \"xdist help spec\".  (type \"xdist help spec\" for details)",
    )
    # ...

加载测试用例

pytest-xdist 加载 pytest 测试用例的过程和普通的 pytest 测试用例加载过程相同,它会递归地查找当前目录及其子目录下的所有 test_*.py 文件和 *_test.py 文件,以及所有以 test_ 或者 test 开头的测试函数。这个过程是通过 pytest_collection_modifyitems 钩子函数来实现的,它会在 pytest 执行测试用例前被调用,从而修改 pytest 收集到的测试用例列表。这里是相关的源码:

def pytest_collection_modifyitems(items):
    config = items[0].session.config
    if config.option.numprocesses and not config.option.dist:
        config.option.dist = "load"
    # ...

分发测试用例

pytest-xdist 根据用户指定的分发模式,将测试用例分发到多个进程或主机上。这个过程是通过 pytest_runtestloop 函数来实现的,它是 pytest 执行测试用例的入口函数。在 pytest_runtestloop 函数中,pytest-xdist 根据用户指定的分发模式,创建多个子进程或者多个主机,然后将测试用例分发给每个子进程或主机执行。这里是相关的源码:

def pytest_runtestloop(session):
    # ...
    if session.config.option.numprocesses:
        from .dist import load
        return load(session)
    elif session.config.option.dist == "load":
        from .dist import load
        return load(session)
    elif session.config.option.dist == "each":
        from .dist import each
        return each(session)
    # ...

其中,load 函数是用于分发测试用例到多个进程的,each 函数是用于分发测试用例到多个主机的。这里是 load 函数的相关源码:

def load(session):
    numprocesses = session.config.option.numprocesses
    # ...
    if numprocesses <= 0:
        raise ValueError("number of processes must be greater than 0")
    config = session.config
    if config.option.capture == "no":
        config.option.capture = "fd"
    # ...
    else:
        from . import (  # noqa: F401
            box,
            worker,
        )
        with box.Box(config, numprocesses=numprocesses) as box:
            box.makegateways()
            gwlist = box.gwlist()
            result = box.invoke_gateways(gwlist, "start_worker", numprocesses=numprocesses, **box._kwds)
    # ...

在 load 函数中,首先会获取用户指定的进程数,然后根据进程数创建一个 Box 对象。Box 对象是 pytest-xdist 中的一个重要概念,它表示一个运行环境,用于管理多个子进程或主机。在 Box 对象创建完成后,pytest-xdist 会调用 Box 对象的 makegateways 方法,用于创建与子进程或主机的通信通道。然后,pytest-xdist 会调用 Box 对象的 invoke_gateways 方法,用于在所有子进程或主机上启动测试用例执行。在 invoke_gateways 方法中,pytest-xdist 会将要执行的测试用例发送给每个子进程或主机,然后等待所有子进程或主机执行完成。

执行测试用例

在每个子进程或主机上,pytest-xdist 会执行分配给它的测试用例。具体来说,pytest-xdist 会在每个子进程或主机上启动一个 Python 进程,然后在该进程中执行测试用例。这个过程是通过 pytest_runtest_protocol 函数来实现的,它是 pytest 执行单个测试用例的函数。在 pytest_runtest_protocol 函数中,pytest-xdist 会将要执行的测试用例通过 execnet 模块发送给子进程或主机,然后等待执行结果。这里是相关的源码:

def pytest_runtest_protocol(item, nextitem):
    # ...
    if config.option.numprocesses:
        from .dist import worker
        return worker.worker_runtest(item=item, nextitem=nextitem)
    elif config.option.dist == "load":
        from .dist import worker
        return worker.worker_runtest(item=item, nextitem=nextitem)
    elif config.option.dist == "each":
        return runtestprotocol(item, nextitem=nextitem)
    # ...

在分发测试用例到多个主机时,pytest-xdist 会将测试用例通过 SSH 协议发送到每个主机,然后在每个主机上启动一个 Python 进程,并在该进程中执行测试用例。这个过程是通过 ssh_run 函数来实现的,它是 pytest-xdist 中的一个辅助函数,用于执行远程命令。这里是相关的源码:

def ssh_run(host, command, capture=True):
    # ...
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(hostname=host, username=username, password=password, port=port)
    with ssh:
        stdin, stdout, stderr = ssh.exec_command(command)
        if capture:
            out = stdout.read().decode()
            err = stderr.read().decode()
            return out, err
        else:
            return None, None

在 ssh_run 函数中,pytest-xdist 使用 Paramiko 模块建立 SSH 连接,然后通过 SSH 协议发送测试用例和执行命令。这个过程中,所有的输入输出都通过 SSH 协议进行传输。

汇总测试结果

在所有子进程或主机上的测试执行完成后,pytest-xdist 会将所有测试结果汇总到主进程中,并输出测试报告。这个过程是通过 pytest_terminal_summary 钩子函数来实现的,它会在 pytest 执行完成后被调用,从而输出测试报告。这里是相关的源码:

def pytest_terminal_summary(terminalreporter):
    session = terminalreporter.config.session
    if session.testsfailed and session.config.option.looponfail:
        terminalreporter.write("re-running failed tests...\n")
        return pytest_runtestloop(session)
    # ...

在 pytest_terminal_summary 函数中,pytest-xdist 会检查测试结果,然后输出测试报告。如果测试用例执行失败,并且用户指定了 --looponfail 参数,pytest-xdist 会自动重试执行测试用例。

清理资源

在所有测试结果都汇总完成后,pytest-xdist 会清理所有的资源,包括关闭分配给每个子进程或主机的 Python 进程、删除临时文件等。这个过程是通过 pytest_unconfigure 钩子函数来实现的,它会在 pytest 执行完成后被调用,从而清理 pytest-xdist 使用的所有资源。这里是相关的源码:

def pytest_unconfigure(config):
    # ...
    if hasattr(config, "_xdist_worker_collection"):

pytest-xdist 参数浅解:

  1. -n: 指定分发模式,可以是一个数字,表示分发到多少个进程;也可以是一个字符串,表示分发到多少个主机(如 -n 4 表示分发到 4 个进程,-n 4 --hosts=host1,host2,host3,host4 表示分发到 4 个主机)。

  2. --numprocesses: 指定分发到多少个进程执行测试用例。

  3. --tx: 指定分发到多少个主机执行测试用例,格式为 popen//ssh:user@host:port

  4. --max-worker-restart: 指定在某个子进程或主机上测试用例执行失败时的最大重试次数。

  5. --rsyncdir: 指定用于同步文件的目录,该目录下的所有文件会被同步到所有子进程或主机上。

  6. --rsyncignore: 指定需要忽略同步的文件或目录的规则。

  7. --boxed: 指定在子进程或主机中使用进程隔离(process isolation)模式执行测试用例。

  8. --capture: 指定在子进程或主机中使用的输出捕获模式,可以是 fdsys 或者 no

  9. --ignore: 指定需要忽略的测试文件或目录。

  10. --looponfail: 指定在测试用例执行失败时自动重试的次数。


以下是我收集到的比较好的学习教程资源,虽然不是什么很值钱的东西,如果你刚好需要,可以评论区,留言【777】直接拿走就好了

pytest-xdist分布式测试原理浅析,软件测试,性能测试,pytest,程序人生,软件测试,分布式,经验分享,python

pytest-xdist分布式测试原理浅析,软件测试,性能测试,pytest,程序人生,软件测试,分布式,经验分享,python

各位想获取资料的朋友请点赞 + 评论 + 收藏,三连!

三连之后我会在评论区挨个私信发给你们~文章来源地址https://www.toymoban.com/news/detail-642777.html

到了这里,关于pytest-xdist分布式测试原理浅析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 分布式锁实现方案-基于zookeeper的分布式锁实现(原理与代码)

    目录 一、基于zookeeper的分布式锁 1.1 基于Zookeeper实现分布式锁的原理 1.1.1 分布式锁特性说明 1.1.1.1 特点分析 1.1.1.2 本质 1.1.2 Zookeeper 分布式锁实现原理 1.1.2.1 Zookeeper临时顺序节点特性 1.1.2.2 Zookeeper满足分布式锁基本要求 1.1.2.3 Watcher机制 1.1.2.3 总结 1.2 分布式锁流程说明 1.2.1

    2024年04月24日
    浏览(33)
  • 分布式系统原理

    高可用是指系统无中断的执行功能的能力,代表了系统的可用程度,是进行系统设计时必须要遵守的准则之一。 而高可用的实现方案,无外乎就是冗余,就存储的高可用而言,问题不在于如何进行数据备份,而在于如何规避数据不一致对业务造成的影响。 对于分布式系统而

    2024年02月05日
    浏览(36)
  • Redission分布式锁原理初探

    在多线程并发请求当中,为了保证我们的资源同一时刻只有一个线程进行操作(如商品超卖问题、购票系统等),我们通常要添加锁机制,如ReentrantLock,也就是可重入的互斥锁,与synchronized功能类似,因为比较灵活,所以经常使用。这在单机情况下是没有问题的,但在多节点

    2024年02月05日
    浏览(34)
  • Redis分布式锁实现原理

    在早期互联网的架构中,一个应用都是单机进行部署,这种情况下,利用JDK提供的锁机制即可解决共享数据在多线程场景下的线程安全问题,但随着技术的发展,分布式系统架构逐渐普及,在分布式架构中,由于一个应用会进行多机部署,服务器实例之间的JVM是互相独立的,

    2024年02月16日
    浏览(31)
  • 分布式存储测试模型

    分布式存储测试模型 (1) Cosbench 可以通过对象接口,模拟对象数据访问时数据高并发以及大带宽写入数据时海量小文件数据写入的 OPS( 每秒可以读取或者写入的文件数量 ) 以及大容量数据写入时的带宽 ( 每秒写入和读取的数据量 ) 性能。 (2) Vdbench 可 基 于 文 件 系 统, 模 拟

    2024年02月11日
    浏览(39)
  • Redisson分布式锁 原理&源码 分析

    获取锁的Lua脚本: 释放锁的Lua脚本: tryLock()底层代码分析 time :剩余的等待重试时间 ttl :现被持有的锁的剩余有效时间 计算尝试获取锁所消耗的时间,然后再计算出等待获取锁的剩余时间time, 如果time=0,则不再重试了直接返回获取锁失败, 如果time0,则通过subscribe去

    2024年02月11日
    浏览(50)
  • ES 的分布式架构原理能说一下么(ES 是如何实现分布式的啊)?

    目录 一、面试官心理分析 二、面试题剖析         在搜索这块,lucene 是最流行的搜索库。几年前业内一般都问,你了解 lucene 吗?你知道倒排索引的原理吗?现在早已经 out 了,因为现在很多项目都是直接用基于 lucene 的分布式搜索引 擎—— ElasticSearch ,简称为 ES 。  

    2024年03月15日
    浏览(35)
  • 【Locust分布式压力测试】

    Locust分布式压力测试 https://docs.locust.io/en/stable/running-distributed.html Distributed load generation A single process running Locust can simulate a reasonably high throughput. For a simple test plan and small payloads it can make more than a thousand requests per second, possibly over ten thousand if you use FastHttpUser. But if your test plan i

    2024年04月22日
    浏览(23)
  • Jmeter分布式压力测试

    目录 1、场景 2、原理 3、注意事项 4、slave配置 5、master配置 6、脚本执行 在做性能测试时,单台机器进行压测可能达不到预期结果。主要原因是单台机器压到一定程度会出现瓶颈。也有可能单机网卡跟不上造成结果偏差较大。 例如4C8G的window server机器,使用UI方式,最高压测

    2024年02月08日
    浏览(32)
  • Redis实现分布式锁原理(面试重点)

    一、为什么使用分布式锁? 本地锁的局限性( synchronized ): 本地锁只能锁住当前服务,只能保证自己的服务,只有一个线程可以访问,但是在服务众多的分布式环境下,其实是有多个线程同时访问的同一个数据,这显然是不符合要求的。 ·分布式锁的概念: 分布式锁指的是,

    2024年02月10日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包