如何让pytest按上次执行时间排序测试并结合--ff选项?
pytest 按上次执行时间排序测试用例(结合失败用例优先)
现成插件方案
可以直接使用pytest-duration-order插件,它支持基于上次测试的执行时长对用例排序,同时能和pytest原生的--ff(失败用例优先)选项兼容:
- 安装插件:
pip install pytest-duration-order - 使用方式:运行测试时加上
--duration-order参数,同时配合--ff即可实现「先跑失败用例,剩余用例按上次执行时间排序」的需求。默认是长耗时用例优先,如果需要短耗时优先,可加上--duration-order-reverse参数。
手动编写插件实现
如果需要自定义逻辑,可通过pytest的钩子函数结合内置缓存机制实现,步骤如下:
1. 记录测试用例的执行时长
在项目根目录的conftest.py中添加钩子函数,将每个测试的执行时长存入pytest缓存:
def pytest_runtest_makereport(item, call): if call.when == "call": # 从缓存中读取已有的时长记录,没有则初始化空字典 cache = item.config.cache test_durations = cache.get("test_durations", {}) # 存入当前测试的执行时长 test_durations[item.nodeid] = call.duration cache.set("test_durations", test_durations)
2. 自定义测试用例排序逻辑
同样在conftest.py中添加pytest_collection_modifyitems钩子,实现「失败用例优先,剩余用例按上次时长排序」的逻辑:
def pytest_collection_modifyitems(config, items): cache = config.cache # 获取上次测试的失败用例列表(pytest原生--ff依赖的缓存键) last_failed = cache.get("cache/lastfailed", {}) # 获取之前记录的测试时长 test_durations = cache.get("test_durations", {}) # 拆分失败用例和普通用例 failed_items = [] normal_items = [] for item in items: if item.nodeid in last_failed: failed_items.append(item) else: normal_items.append(item) # 对普通用例按上次执行时长排序(这里设为长耗时优先,reverse=False则为短耗时优先) normal_items.sort(key=lambda x: test_durations.get(x.nodeid, 0), reverse=True) # 重新组合用例列表:失败用例在前,排序后的普通用例在后 items[:] = failed_items + normal_items
3. 使用方式
直接运行测试时加上--ff参数即可,无需额外参数:
pytest --ff
第一次运行时无缓存数据,排序不生效;从第二次运行开始,就会按照预期逻辑执行。
内容的提问来源于stack exchange,提问作者David Masip
相关产品推荐
相关产品推荐

