使用pytest-xdist让自动化并行测试变得轻松简单

server/2025/3/12 9:16:02/

关注开源优测不迷路

大数据测试过程、策略及挑战

测试框架原理,构建成功的基石

自动化测试工作之前,你应该知道的10条建议

自动化测试中,重要的不是工具

在实际的项目中即便没有数千个测试,也有 100 个测试。当你运行 pytest 时,测试运行器会按顺序执行这些测试,要花很长时间才能完成测试。


要是有更好的方法呢?一种可以有效利用资源、并行运行测试,并减少整体测试执行时间以及 CI/CD 流水线时间的方法。


这将使测试更高效,能更快地反馈代码变更的情况,还能改进整个开发流程,同时降低你的 CI/CD 运行成本。


Pytest 引入了一个强大的插件 pytest-xdist,它能让你无缝地分发和执行测试。


在本文中,我们将详细探究 pytest-xdist,了解为什么要使用 pytest-xdist 进行测试并行化,以及 pytest-xdist 插件的优势。


我们还将展示一个实际示例,了解 pytest-xdist 的工作原理,并观察使用它来并行化测试的好处。


最后,我们将为你提供使用 pytest-xdist 并行化测试时的重要最佳实践。通过学习本文,你将对如何利用 pytest-xdist 实现更快的测试执行有深入的理解。

在阅读完本文后,你将:


  • 很好地理解测试并行化以及它为什么很重要。

  • 如何利用 pytest-xdist 插件来并行化测试。

  • 并行化测试时的重要最佳实践。

什么是测试并行化?


测试并行化是指并发运行多个测试,从而减少整体测试执行时间。


它将测试分布在多个资源上,比如多个 CPU 核心、线程或机器上,并同时执行这些测试。


我们在这里对测试并行化进行了非常详细的介绍,强烈建议你去查看一下。


为什么要并行化测试?


既然已经清楚了并行运行测试的含义,那为什么要这么做呢?


在顺序执行测试时,执行时间会随着测试数量呈线性增长。


这还需要更长的计算时间,使得你的 CI/CD 流水线更慢且成本更高。


大多数 CI/CD 服务是根据执行分钟数来收费的。测试花费的时间越长,你支付的费用就越多。


除了 CI/CD 方面,缓慢的开发反馈可能会让人沮丧。你希望尽快知道你的代码变更是否会导致测试失败。


想象一下,更改了一个变量,然后运行一个需要 30 分钟才能完成的测试套件。


选择性地运行测试并不总是可行的,尤其是当你在处理一个大型项目,并且需要测试端到端的功能时。


这就是测试并行化发挥作用的地方,它能让你以极快的速度运行测试。


pytest-xdist 概述


pytest-xdist 是一个很受欢迎的 pytest 插件,它使你能够在多台机器或多个 CPU 上并行执行测试。


这让你可以通过将测试分布到可用资源上来加快测试套件的运行速度,从而减少整体测试执行时间。


使用 pytest-xdist,你可以指定用于并行执行的测试进程(工作进程)数量。这使你能够根据系统的能力自定义并行化的程度。


注意 - 由于 pytest-xdist 的实现方式,-s/--capture=no 选项不起作用。我们在这里详细介绍了标准输出 / 标准错误输出的捕获方法。


让我们来看看如何使用 pytest-xdist 进行测试并行化。

实际示例


考虑一个简单的测试套件,它包含 10 个测试,每个测试都故意设置了 1 秒钟的延迟。

开始

我们的示例仓库结构如下:

f2a3a7beaf8928b862392e7ed97d2e1e.png

测试代码

看看下面的测试代码:

# tests/test_pytest_xdist.py
import pytest
import time

## 初始化 10 个测试,每个测试故意延迟 1 秒

deftest_with_xdist_01():
    time.sleep(1)
    assertTrue

deftest_with_xdist_02():
    time.sleep(1)
    assertTrue

deftest_with_xdist_03():
    time.sleep(1)
    assertTrue

deftest_with_xdist_04():
    time.sleep(1)
    assertTrue

deftest_with_xdist_05():
    time.sleep(1)
    assertTrue

deftest_with_xdist_06():
    time.sleep(1)
    assertTrue

deftest_with_xdist_07():
    time.sleep(1)
    assertTrue

deftest_with_xdist_08():
    time.sleep(1)
    assertTrue

deftest_with_xdist_09():
    time.sleep(1)
    assertTrue

deftest_with_xdist_10():
    time.sleep(1)
    assert True

我们的测试代码包含 10 个简单的测试,每个测试都故意延迟了 1 秒。

运行测试

让我们使用 Pytest-xdist 运行测试:

pytest -v

你会得到以下输出:

9c5b263118fe75708bc0ee6c16472bbc.jpeg

请注意,测试执行总共花费了 10.11 秒。


现在使用 Pytest-xdist(使用 5 个工作进程)来运行测试:

pytest -v -n 5
这次你会得到以下输出:

14190c3eed1904f5dc3a2d14cd7779ab.jpeg


‍‍

看看执行时间。3.91 秒!比不使用 pytest-xdist 运行测试时的时间少了一半还多。


如果你不想指定工作进程的数量,你可以让 pytest-xdist 使用关键字 auto 来管理。

pytest -v -n auto

你会得到以下输出:

c9bab5ddccf050bc31832645a6436b6c.jpeg

选择工作进程的数量可能有点棘手。你可以从少量的工作进程开始,然后根据你的硬件资源和测试套件的特点逐渐增加数量。


或者,如果你想让 pytest-xdist 根据可用资源自动确定工作进程的数量,你可以使用 -n auto 标志。


自定义 pytest-xdist


pytest-xdist 提供了几个选项来自定义并行测试执行过程。


以下是一些最常用的选项:


  • 自动进程分配
    • 使用 pytest -n auto 可以自动利用与你机器上物理 CPU 核心数量相同的进程数。

    • 或者,使用 pytest -n logical 来使用逻辑 CPU 核心。这需要 psutil 包,如果无法获取逻辑核心数,则默认使用物理核心。

  • 显式进程计数
    • 你可以直接指定进程数量,例如 pytest -n 8

  • 自定义配置
    • 设置 PYTEST_XDIST_AUTO_NUM_WORKERS 环境变量,或者在 conftest.py 中实现 pytest_xdist_auto_num_workers 钩子函数,来为 -n auto 和 -n logical 定义自定义行为。

  • 进一步的并行化控制
    • 使用 --maxprocesses 限制最大工作进程数,使用 --max-worker-restart 设置重启限制。

  • 测试分布策略
    • --dist load

      默认模式,将测试分发给任何可用的工作进程。

    • --dist loadscope

      按模块或类对测试进行分组,以确保它们在同一个进程中运行。

    • --dist loadfile

      按文件对测试进行分组。

    • --dist loadgroup

      按自定义的组标记对测试进行分组,以确保它们在同一个工作进程中运行。

    • --dist worksteal

      将测试从不太繁忙的工作进程重新分配给空闲的工作进程,以优化夹具的重用并处理不同的测试持续时间。

    • --dist no

      正常模式,按顺序执行测试,不进行分发。


你可以在 pytest-xdist 的文档中找到更多选项和配置。


使用 pytest-xdist 并行化测试的最佳实践


让我们快速了解一下使用 pytest-xdist 并行化测试时的一些重要最佳实践:


  • 尽量减少插件使用

    插件可以丰富 Pytest 的功能,但可能会减慢测试执行速度。只包含必要的插件以保持最佳性能。不必要的插件会使你的测试设置变得臃肿,导致执行时间变慢。

  • 在不同环境中测试

    在不同的环境(例如,本地开发机器、CI/CD 服务器、类似生产环境)中测试你的并行执行设置,以确保兼容性和稳定性。

  • 逐步扩展工作进程数量

    从少量的并行工作进程开始,然后根据系统的容量和测试套件的性质逐渐增加数量。监控资源使用情况和测试结果以确保稳定性。

  • 确保可重复性

    测试可以按任意顺序运行且相互独立是一个良好的实践。像 pytest-randomly 这样的插件非常有用,可以与 pytest-xdist 这样的并行测试工具结合使用。

  • 简化测试套件

    在实现并行执行之前,通过减少不必要的设置和清理活动、最小化测试间的依赖关系以及删除重复项来优化你的测试套件。

  • 隔离测试数据

    当测试并行运行时,共享数据可能会导致不可预测的结果。为每个测试使用隔离的数据集,或者使用夹具来确保每个测试都有一个全新的设置,以防止冲突并确保测试可以在无干扰的情况下并发运行。

  • 监控和优化资源分配

    在测试运行期间密切关注 CPU 和内存的使用情况,以便动态调整并行工作进程的数量。系统过载可能会导致性能下降和测试结果不稳定。

  • 利用高效的排序策略

    实施智能的测试排序策略,例如按测试持续时间分组或按依赖关系分类。这种方法可以通过最小化等待可用工作进程的时间并优化设置和清理操作的使用来减少总运行时间。


结论


本文就介绍到这里。


希望这篇文章对你有帮助,并且你学到了一些新的知识。


pytest-xdist 是一个很有用的用于并行化测试的插件,它允许你将测试分布到多个进程中,以便更快地执行测试。


我们详细介绍了 pytest-xdist,包括为什么要使用它以及如何通过实际示例来使用它。


我们还展示了如何将 pytest-randomly 与 pytest-xdist 结合使用,以实现更快且随机的测试执行(这是防止测试结果不稳定的一个好方法)。


最后,你学到了使用 pytest-xdist 并行化测试时的一些重要最佳实践。


我强烈建议你在自己的测试套件中尝试使用 pytest-xdist,并探索并行测试执行的好处,尤其是当你的测试套件不断增长时。


http://www.ppmy.cn/server/174411.html

相关文章

Go语言单元测试和基准测试

单元测试和基准测试 在Go语言中,单元测试和基准测试是两种不同类型的测试,它们的目的、使用场景以及实现方式都有所不同。以下是它们的主要区别: 1. 目的 单元测试: 目的是验证代码单元(通常是函数或方法&#xff09…

卡顿优化(matrix与blockcanary)

卡顿优化(matrix与blockcanary) 在Android应用开发中,流畅的用户体验是产品成功的关键因素之一。然而,随着应用功能的不断丰富,卡顿问题也随之而来。本文将深入探讨Android应用中的卡顿问题,包括卡顿的原因、检测方法以及优化策略,并重点介绍两款强大的卡顿检测工具:M…

SQL语句执行顺序是什么?

理解SQL语句的执行顺序对于优化查询和提高数据库性能非常重要。 1. SQL语句的执行过程 当我们执行一条SQL语句时,MySQL会按照一定的顺序解析和执行这条语句。这个过程可以分为以下几个阶段: 1.1 解析SQL语句 MySQL首先会解析SQL语句,将其分…

Flutter 学习之旅 之 flutter 不使用插件,实现简单带加载动画的 LoadingToast 功能

Flutter 学习之旅 之 flutter 不使用插件,实现简单带加载动画的 LoadingToast 功能 目录 Flutter 学习之旅 之 flutter 不使用插件,实现简单带加载动画的 LoadingToast 功能 一、简单介绍 二、LoadingToast 三、简单案例实现 四、关键代码 一、简单…

Spring Boot 与 Spring MVC 有何不同

Spring Boot 和 Spring MVC 都是 Spring 框架的一部分,但它们有不同的目标和功能。以下是它们之间的主要区别: 1. 核心目标 Spring Boot:Spring Boot 的目标是简化 Spring 应用的配置和部署。它通过提供默认配置和嵌入式服务器(如 Tomcat、Je…

【Java开发指南 | 第三十四篇】IDEA没有Java Enterprise——解决方法

读者可订阅专栏:Java开发指南 |【CSDN秋说】 文章目录 1、新建Java项目2、单击项目名,并连续按两次shift键3、在搜索栏搜索"添加框架支持"4、勾选Web应用程序5、最终界面6、添加Tomcat 1、新建Java项目 2、单击项目名,并连续按两次…

面试基础--高并发高可用架构深度实践:降级熔断(Hystrix vs Sentinel)核心原理与源码解析

高并发高可用架构深度实践:降级熔断(Hystrix vs Sentinel)核心原理与源码解析 引言:从抖音春晚红包看熔断降级的重要性 2021年春晚抖音红包互动量达703亿次,其支付系统通过智能熔断机制在流量洪峰中保持99.99%可用性…

Elasticsearch 提升查询精度

在Elasticsearch中,查询精度(即查准率,Precision)是衡量搜索结果相关性的重要指标。如果查询结果包含许多无关文档,用户体验会大打折扣。以下是提升查询精度的几种方法: 1. 优化查询方式 使用 match_phra…