pytest-xdist分布式测试原理浅析
目录
pytest-xdist执行流程:
pytest-xdist 模块结构:
pytest-xdist分布式测试原理:
pytest-xdist源码浅读:
pytest-xdist执行流程:
-
解析命令行参数:pytest-xdist 会解析命令行参数,获取用户指定的分发模式、进程数、主机列表等信息。
-
加载测试用例:pytest-xdist 会加载所有的 pytest 测试用例,包括在当前目录和子目录下的所有测试文件和测试函数。
-
分发测试用例:根据用户指定的分发模式,pytest-xdist 会将测试用例分发到多个进程或主机上执行。如果是分发到多个进程,pytest-xdist 会创建多个子进程,每个子进程都会执行一部分测试用例。如果是分发到多个主机,pytest-xdist 会在每个主机上启动一个 Python 进程,然后将测试用例分发给每个 Python 进程执行。
-
执行测试用例:在每个进程或主机上,pytest-xdist 会执行分配给它的测试用例。每个进程或主机上的测试执行都是独立的,它们之间没有任何数据共享或通信。
-
汇总测试结果:在所有进程或主机上的测试执行完成后,pytest-xdist 会将所有测试结果汇总到主进程中,并输出测试报告。在汇总测试结果的过程中,pytest-xdist 还会根据用户指定的选项合并相同的测试结果,比如合并多个进程或主机上的相同测试用例结果。
-
清理资源:在所有测试结果都汇总完成后,pytest-xdist 会清理所有的资源,包括关闭分配给每个进程或主机的 Python 进程、删除临时文件等。
需要注意的是,pytest-xdist 的执行流程是一个异步的过程,不同进程或主机上的测试执行是并行的,它们之间没有任何阻塞或等待
pytest-xdist 模块结构:
-
xdist模块:这是 pytest-xdist 的主模块,包含了分发测试用例的主要逻辑。在xdist模块中,主要包含了以下几个子模块:looponfail: 在测试用例执行失败时自动重试的逻辑。loadfile: 加载分布式测试配置文件的逻辑。rsync: 在多个主机之间同步文件的逻辑。newhooks: 扩展 pytest 的钩子函数以支持分布式测试的逻辑。
-
testing模块:这是 pytest-xdist 的测试模块,包含了对 pytest-xdist 的单元测试和集成测试。 -
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.configif 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 loadreturn load(session)elif session.config.option.dist == "load":from .dist import loadreturn load(session)elif session.config.option.dist == "each":from .dist import eachreturn 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.configif config.option.capture == "no":config.option.capture = "fd"# ...else:from . import ( # noqa: F401box,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 workerreturn worker.worker_runtest(item=item, nextitem=nextitem)elif config.option.dist == "load":from .dist import workerreturn 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, errelse: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.sessionif 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 参数浅解:
-n: 指定分发模式,可以是一个数字,表示分发到多少个进程;也可以是一个字符串,表示分发到多少个主机(如-n 4表示分发到 4 个进程,-n 4 --hosts=host1,host2,host3,host4表示分发到 4 个主机)。
--numprocesses: 指定分发到多少个进程执行测试用例。
--tx: 指定分发到多少个主机执行测试用例,格式为popen//ssh:user@host:port。
--max-worker-restart: 指定在某个子进程或主机上测试用例执行失败时的最大重试次数。
--rsyncdir: 指定用于同步文件的目录,该目录下的所有文件会被同步到所有子进程或主机上。
--rsyncignore: 指定需要忽略同步的文件或目录的规则。
--boxed: 指定在子进程或主机中使用进程隔离(process isolation)模式执行测试用例。
--capture: 指定在子进程或主机中使用的输出捕获模式,可以是fd、sys或者no。
--ignore: 指定需要忽略的测试文件或目录。
--looponfail: 指定在测试用例执行失败时自动重试的次数。
以下是我收集到的比较好的学习教程资源,虽然不是什么很值钱的东西,如果你刚好需要,可以评论区,留言【777】直接拿走就好了


各位想获取资料的朋友请点赞 + 评论 + 收藏,三连!
三连之后我会在评论区挨个私信发给你们~
相关文章:
pytest-xdist分布式测试原理浅析
目录 pytest-xdist执行流程: pytest-xdist 模块结构: pytest-xdist分布式测试原理: pytest-xdist源码浅读: pytest-xdist执行流程: 解析命令行参数:pytest-xdist 会解析命令行参数,获取用户…...
研发工程师玩转Kubernetes——PVC通过storageClassName进行延迟绑定
不同的PV可以使用相同的StorageClass,它们是一对多的关系。 PV可以设置节点亲和性。比如下图,local-storage-class-waitforfirstconsumer-pv-ubuntuc只能在节点ubuntuc上;local-storage-class-waitforfirstconsumer-pv-ubuntud只能在节点ubu…...
6.利用matlab完成 符号矩阵的秩和 符号方阵的逆矩阵和行列式 (matlab程序)
1.简述 利用M文件建立矩阵 对于比较大且比较复杂的矩阵,可以为它专门建立一个M文件。下面通过一个简单例子来说明如何利用M文件创建矩阵。 例2-2 利用M文件建立MYMAT矩阵。(1) 启动有关编辑程序或MATLAB文本编辑器,并输入待建矩阵:(2) 把…...
python获取类名__qualname__,解决django接口ObjectDoesNotExist异常寻找model的问题
在django项目中,经常使用类似Model.objects.get(id1)的方法取对象,默认抛出的异常是ObjectDoesNotExist类型,通过try catch可以把异常捕获,获取的异常是Model.DoesNotExist类型, 要获知其类名,可以使用__na…...
电流的测量(分流电流表)
在当今的大多数仪器应用中,可以使用两种常见的电流测量方法:分流电流表方法和反馈电流表方法。分流电流表方法通常与通用数字万用表 (DMM)一起使用,用于测量分流电阻器上的电压测量值。该电压测量结果与已知的电阻值相结合,得出电…...
Leetcode每日一题:23. 合并 K 个升序链表(2023.8.12 C++)
目录 23. 合并 K 个升序链表 题目描述: 实现代码与解析: 优先级队列: 原理思路: 23. 合并 K 个升序链表 题目描述: 给你一个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表…...
越南的区块链和NFT市场调研
越南的区块链和NFT市场调研 基本介绍 https://zh.wikipedia.org/wiki/%E8%B6%8A%E5%8D%97 语言文字: 越南语, 文字以国语字(越南罗马字)为主,汉喃文(汉字) 货币:越南盾 人口(2022…...
MySQL常用语句
当涉及到与关系型数据库进行交互时,以下是一些常用的 SQL 语句,可以帮助你进行数据查询、插入、更新和删除等操作: 查询数据: 查询所有数据:SELECT * FROM table_name; 查询特定列数据:SELECT column1, col…...
Mongodb:业务应用(1)
环境搭建参考:mongodb:环境搭建_Success___的博客-CSDN博客 需求: 在文章搜索服务中实现保存搜索记录到mongdb 并在搜索时查询出mongdb保存的数据 1、安装mongodb依赖 <dependency><groupId>org.springframework.data</groupI…...
【vue】vue中按钮权限控制:
文章目录 一、获取权限码二、三种按钮级别的权限控制方式【1】函数方式【2】组件方式【3】指令方式 一、获取权限码 要做权限控制,肯定需要一个code,无论是权限码还是角色码都可以,一般后端会一次性返回,然后全局存储起来就可以了…...
【博客695】k8s subPathExpr作用
k8s subPathExpr作用 场景: 对于一个deployment或者job拉起的服务,所有pod都是一样的配置,如果都挂载了宿主机的同一个目录,那么就会互相干扰,我们希望挂载相同目录,且在这个目录下,每个pod建立…...
微信小程序中键盘弹起输入框自动跳到键盘上方处理
效果展示 键盘未弹起时 键盘弹起后: 实现方式 话就不多说了 我直接贴代码了 原理就是用你点击的输入框的底部 距离顶部的位置 减去屏幕高度除以2,然后设成负值,再将这个值给到最外层相对定位的盒子的top属性,这样就不会出现顶…...
excel将主信息和明细信息整理为多对多(每隔几行空白如何填充)
excel导出的数据是主信息和明细信息形式。 方法如下:1、首先,从第一个单元格开始选中要填充的数据区域。2、按CtrlG或者F5调出定位对话框,点击左下角的【定位条件】。3、在【定位条件】中选择【空值】,然后点击【确定】按钮。4、按照上述操作…...
卷积神经网络实现彩色图像分类 - P2
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍦 参考文章:365天深度学习训练营-第P2周:彩色识别🍖 原作者:K同学啊 | 接辅导、项目定制🚀 文章来源:K同学的学习圈子…...
【博客694】k8s kubelet 状态更新机制
k8s kubelet 状态更新机制 场景: 当 Kubernetes 中 Node 节点出现状态异常的情况下,节点上的 Pod 会被重新调度到其他节点上去,但是有的时候我们会发现节点 Down 掉以后,Pod 并不会立即触发重新调度,这实际上就是和 K…...
【博客692】grafana如何解决step动态变化时可能出现range duration小于step
grafana如何解决step动态变化时可能出现range duration小于step 1、grafana中的step和resolution grafana中的 “step” grafana本身是没有提供step参数的,因为仪表盘根据查询数据区间以及仪表盘线条宽度等,对于不同查询,相同的step并不能…...
eNSP:ibgp的破水平切割练习
实验要求: 拓扑展示: 命令操作: R1: <Huawei>sys [Huawei]sys r1 [r1]int g 0/0/1 [r1-GigabitEthernet0/0/1]ip add 12.1.1.1 24 [r1-GigabitEthernet0/0/1]int lo0 [r1-LoopBack0]ip add 1.1.1.1 24 [r1-LoopBack0]osp…...
maven是什么?安装+配置
目录 1.什么是maven? 1.2.maven的核心功能是什么? 2.Maven安装配置 2.1Maven的安装 2.2Maven环境配置 1.配置 MAVEN_HOME ,变量值就是你的 maven 安装的路径(bin 目录之前一级目录) 2.将MAVEN_HOME 添加到Path系…...
基于长短期神经网络LSTM的多分类代码
目录 背影 摘要 LSTM的基本定义 LSTM实现的步骤 基于长短期神经网络LSTM的股票预测 MATALB编程实现,附有代码:基于长短期神经网络LSTM的多分类代码,基于LSTM的多分类预测-深度学习文档类资源-CSDN文库 https://download.csdn.net/download/abc991835105/88184779 效果图 结果…...
利用爬虫爬取图片并保存
1 问题 在工作中,有时会遇到需要相当多的图片资源,可是如何才能在短时间内获得大量的图片资源呢? 2 方法 我们知道,网页中每一张图片都是一个连接,所以我们提出利用爬虫爬取网页图片并下载保存下来。 首先通过网络搜索…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
Axure 下拉框联动
实现选省、选完省之后选对应省份下的市区...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
