如何用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个随机长测试,多次执行后覆盖所有长测试的场景。
- 在项目根目录创建
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
- 运行命令示例:
# 跑所有快速测试 + 随机5个长测试 pytest --num-long-tests=5
- GitLab CI配置示例(
.gitlab-ci.yml):
test: script: - pytest --num-long-tests=5 only: - pushes
方案二:按时间限制运行,超时后标记剩余长测试为xfail
适合控制总测试时长(比如2小时),超时后自动跳过剩余长测试的场景。
- 在
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"总测试时长已达上限,跳过当前长测试")
- 运行命令示例(2小时=7200秒):
pytest --max-test-time=7200
- GitLab CI配置示例:
test: script: - pytest --max-test-time=7200 only: - pushes
额外说明
- 两种方案可结合使用,比如同时设置时长上限和长测试数量上限,避免极端情况。
- 随机抽样场景下,无需额外存储记录已运行测试,只要每次抽样数量足够,多次推送后自然能覆盖所有长测试。
- 若不想把未选中的长测试标记为
xfail,可改用pytest.mark.skip,区别是xfail会显示为“预期失败”,skip显示为“跳过”,根据CI状态需求选择。
内容的提问来源于stack exchange,提问作者HerpDerpington
相关产品推荐
相关产品推荐

