You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用pytest随机运行部分长测试?数值计算CI优化需求

用pytest实现快速测试全跑+随机/限时运行长测试的方案

前置准备:给测试打标记

先给两类测试分别添加pytest标记,方便后续筛选:

import pytest

# 快速测试标记
@pytest.mark.fast
def test_fast_calculation():
    assert 1 + 1 == 2

# 长测试标记
@pytest.mark.long
def test_large_grid_integration():
    # 耗时数分钟的数值计算逻辑
    assert result == expected

方案一:固定数量随机运行长测试

适合每次推送固定跑N个随机长测试,多次执行后覆盖所有长测试的场景。

  1. 在项目根目录创建conftest.py,添加自定义参数和筛选逻辑:
import pytest
import random

def pytest_addoption(parser):
    parser.addoption(
        "--num-long-tests",
        type=int,
        default=0,
        help="随机运行的长测试数量(默认:0)"
    )

def pytest_collection_modifyitems(config, items):
    # 分离三类测试:快速、长、未标记
    fast_tests = [item for item in items if "fast" in item.keywords]
    long_tests = [item for item in items if "long" in item.keywords]
    other_tests = [item for item in items if "fast" not in item.keywords and "long" not in item.keywords]

    # 必跑所有快速测试和未标记测试
    selected_tests = fast_tests + other_tests

    # 随机选择指定数量的长测试,剩余标记为预期失败
    num_long = config.getoption("--num-long-tests")
    if num_long > 0 and long_tests:
        random.shuffle(long_tests)
        selected_tests += long_tests[:num_long]
        for test in long_tests[num_long:]:
            test.add_marker(pytest.mark.xfail(reason="本次运行未选中:随机抽样"))

    # 更新测试执行列表
    items[:] = selected_tests
  1. 运行命令示例:
# 跑所有快速测试 + 随机5个长测试
pytest --num-long-tests=5
  1. GitLab CI配置示例(.gitlab-ci.yml):
test:
  script:
    - pytest --num-long-tests=5
  only:
    - pushes

方案二:按时间限制运行,超时后标记剩余长测试为xfail

适合控制总测试时长(比如2小时),超时后自动跳过剩余长测试的场景。

  1. 在conftest.py中添加时间控制逻辑:
import pytest
import time

def pytest_addoption(parser):
    parser.addoption(
        "--max-test-time",
        type=int,
        default=0,
        help="测试总时长上限(秒,默认:0=无限制)"
    )

def pytest_configure(config):
    # 记录测试启动时间
    config.test_start_time = time.time()

def pytest_runtest_setup(item):
    # 仅对长测试做时间检查
    if "long" not in item.keywords:
        return

    max_time = config.getoption("--max-test-time")
    if max_time <= 0:
        return

    elapsed = time.time() - config.test_start_time
    if elapsed >= max_time:
        # 标记为预期失败并跳过执行
        item.add_marker(pytest.mark.xfail(reason=f"测试超时:总时长超过{max_time}秒"))
        pytest.skip(f"总测试时长已达上限,跳过当前长测试")
  1. 运行命令示例(2小时=7200秒):
pytest --max-test-time=7200
  1. GitLab CI配置示例:
test:
  script:
    - pytest --max-test-time=7200
  only:
    - pushes

额外说明

  • 两种方案可结合使用,比如同时设置时长上限和长测试数量上限,避免极端情况。
  • 随机抽样场景下,无需额外存储记录已运行测试,只要每次抽样数量足够,多次推送后自然能覆盖所有长测试。
  • 若不想把未选中的长测试标记为xfail,可改用pytest.mark.skip,区别是xfail会显示为“预期失败”,skip显示为“跳过”,根据CI状态需求选择。

内容的提问来源于stack exchange,提问作者HerpDerpington

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:23:32