0

0

如何在 pytest 中随机运行部分耗时测试以优化 CI/CD 流程

碧海醫心

碧海醫心

发布时间:2026-01-08 16:12:40

|

241人浏览过

|

来源于php中文网

原创

如何在 pytest 中随机运行部分耗时测试以优化 CI/CD 流程

本文介绍如何在数值计算类项目中,利用 pytest 随机选取并执行部分“长耗时”单元测试,结合历史耗时统计与分组策略,在有限 ci/cd 时间内最大化测试覆盖率与反馈效率。

在科学计算、数值模拟等场景中,单元测试常因需构建大规模网格(如高分辨率空间/时间离散)或执行长时间数值积分而单测耗时数分钟甚至更久。若每次 Git 提交都全量运行所有长耗时测试(long tests),CI 流水线将不堪重负——可能耗费数十小时,严重拖慢开发节奏。此时,不追求单次全覆盖,而追求多次迭代下的统计性覆盖,是更务实的工程选择。

pytest 本身不原生支持“运行 N 个随机测试”或“限时随机执行后标记剩余为预期失败”,但可通过组合策略高效实现目标:

✅ 推荐实践方案

1. 按耗时分类 + 标签标记

首先使用 @pytest.mark 显式区分测试类型,便于后续筛选:

# test_numerics.py
import pytest

@pytest.mark.fast
def test_small_grid_sum():
    assert sum(range(100)) == 4950

@pytest.mark.long
def test_ode_integration_large_grid():
    # 模拟:生成 10000×10000 网格并积分 → 耗时数分钟
    pass

@pytest.mark.long
def test_pde_solver_convergence():
    pass

2. 基于历史耗时的智能随机采样(推荐)

核心思路:维护一个轻量级 JSON 数据库(如 test_durations.json),记录每个 @pytest.mark.long 测试的历史平均耗时:

{
  "test_ode_integration_large_grid": 217.4,
  "test_pde_solver_convergence": 382.1,
  "test_fourier_transform_high_res": 156.8
}

然后编写脚本 select_long_tests.py,按预算时间(如 7200 秒 = 2 小时)随机贪心选取测试(避免超时):

Mangaize
Mangaize

一键将照片转换为动漫风格的AI工具

下载
import json
import random

def select_random_long_tests(budget_sec: float, duration_file: str = "test_durations.json") -> list:
    with open(duration_file) as f:
        durations = json.load(f)

    # 过滤出 long 测试(假设文件名/函数名已知)
    long_tests = list(durations.keys())
    random.shuffle(long_tests)  # 打乱顺序

    selected = []
    remaining = budget_sec
    for test in long_tests:
        if durations[test] <= remaining:
            selected.append(test)
            remaining -= durations[test]
    return selected

# 示例:生成 pytest 命令
selected = select_random_long_tests(7200)
print("pytest -m long -k '" + " or ".join(selected) + "'")

该脚本可集成进 CI 的 before_script 阶段,动态生成执行命令。

3. 规避重复:轮转排列(Round-robin permutation)

为确保长期迭代下所有长测试被覆盖,可预先生成一个固定随机排列,并按 commit 次数取模轮询:

# 在 CI 中:获取当前 commit 数(或 pipeline ID)作为 seed
import random
commits_since_start = int(os.getenv("CI_PIPELINE_ID", "1")) % 1000
random.seed(commits_since_start)
long_tests = ["test_a", "test_b", "test_c", ...]
random.shuffle(long_tests)  # 每次 commit 对应不同 shuffle
selected = long_tests[:5]  # 固定取前 5 个

4. 关键优化:共享昂贵 setup

若多个长测试共用相同的大规模网格或初始化逻辑,务必提取为 pytest.fixture(scope="session") 或模块级缓存,避免重复开销:

@pytest.fixture(scope="session")
def large_computation_grid():
    print("→ Building 10k×10k grid ONCE per session...")
    return np.random.random((10000, 10000))

def test_grid_property_1(large_computation_grid):
    assert large_computation_grid.mean() > 0.4

def test_grid_property_2(large_computation_grid):  # 免费复用!
    assert np.linalg.norm(large_computation_grid) > 1e4

⚠️ 注意事项与总结

  • ❌ 不要依赖 --randomly 插件(如 pytest-randomly)直接随机——它无法控制耗时或数量,且不保证跨 CI 实例的可重现性;
  • ✅ 强烈建议分离 CI 任务:short-tests(每次必跑,
  • ✅ 将 test_durations.json 纳入版本控制(定期更新),或通过 CI 归档自动更新;
  • ✅ 在测试报告中明确标注:“本次执行 long tests: 5/47 (随机采样,预算 2h)”,增强可追溯性;
  • ✅ 对于关键路径(如主算法回归),仍建议保留少量“守门员长测试”(guardian tests)每次必跑。

通过以上策略,你既能将 CI 时间控制在合理范围内,又能借助概率论保障:在连续 10 次随机采样(每次 5 个)后,任一特定 long test 未被执行的概率低于 0.005%((42/47)^10 ≈ 0.000047),真正实现高效、可靠、可持续的数值测试治理

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

406

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

531

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

309

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

74

2025.09.10

session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

306

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

725

2023.10.18

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

88

2025.08.19

自建git服务器
自建git服务器

git服务器是目前流行的分布式版本控制系统之一,可以让多人协同开发同一个项目。本专题为大家提供自建git服务器相关的各种文章、以及下载和课程。

637

2023.07.05

Golang 分布式缓存与高可用架构
Golang 分布式缓存与高可用架构

本专题系统讲解 Golang 在分布式缓存与高可用系统中的应用,涵盖缓存设计原理、Redis/Etcd集成、数据一致性与过期策略、分布式锁、缓存穿透/雪崩/击穿解决方案,以及高可用架构设计。通过实战案例,帮助开发者掌握 如何使用 Go 构建稳定、高性能的分布式缓存系统,提升大型系统的响应速度与可靠性。

27

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.2万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号