关注开源优测不迷路
大数据测试过程、策略及挑战
测试框架原理,构建成功的基石
在自动化测试工作之前,你应该知道的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 秒钟的延迟。
开始
我们的示例仓库结构如下:
测试代码
看看下面的测试代码:
# 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
你会得到以下输出:
请注意,测试执行总共花费了 10.11 秒。
现在使用 Pytest-xdist(使用 5 个工作进程)来运行测试:
pytest -v -n 5
这次你会得到以下输出:
看看执行时间。3.91 秒!比不使用 pytest-xdist 运行测试时的时间少了一半还多。
如果你不想指定工作进程的数量,你可以让 pytest-xdist 使用关键字 auto
来管理。
pytest -v -n auto
你会得到以下输出:
选择工作进程的数量可能有点棘手。你可以从少量的工作进程开始,然后根据你的硬件资源和测试套件的特点逐渐增加数量。
或者,如果你想让 pytest-xdist 根据可用资源自动确定工作进程的数量,你可以使用 -n auto
标志。
自定义 pytest-xdist
pytest-xdist 提供了几个选项来自定义并行测试执行过程。
以下是一些最常用的选项:
- 自动进程分配
- 显式进程计数
-
你可以直接指定进程数量,例如
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,并探索并行测试执行的好处,尤其是当你的测试套件不断增长时。