pytest-ordering 不支持真正自定义执行顺序,仅提供有限相对优先级控制;@pytest.mark.run(order=...) 常因参数化、继承或动态生成导致标记丢失;未标注测试默认归入 order=0 组,按原始发现顺序执行;替代方案是用 pytest_collection_modifyitems 钩子直接干预收集流程实现精准排序。

pytest-ordering 不能真正“自定义”执行顺序,它只支持有限的相对优先级控制(比如 @pytest.mark.run(order=...)),不支持按函数名、参数或运行时条件动态排序。
为什么 @pytest.mark.run(order=...) 常常失效?
这个插件依赖 pytest 的收集阶段对测试函数打标记,但一旦测试用例来自参数化(@pytest.mark.parametrize)、继承自基类、或被 pytest_generate_tests 动态生成,order 标记就可能丢失或应用错位。
- 参数化生成的每个用例会得到独立的节点 ID,但
@pytest.mark.run只能加在原始函数上,无法逐个指定子用例顺序 - 如果多个测试函数没显式标
order,它们会按 pytest 默认的文件/函数名顺序执行,不是“无序”,而是“未覆盖的默认顺序” - 插件不处理 fixture 依赖关系,
order=1的测试若依赖order=5才 setup 的 fixture,仍会报 fixture not ready 错误
pytest-ordering 的 order 参数实际行为
它只定义测试函数之间的相对位置,数值越小越靠前;相同数值的测试按原始发现顺序排列;未标注的测试统一归到 order=0 组(不是“最后”,而是“中间默认组”)。
-
@pytest.mark.run(order=-1)→ 比所有未标或order=0的测试更早执行 -
@pytest.mark.run(order=10)→ 比order=5晚,但比未标注的测试早(因为未标注 ≡order=0) - 两个都写
order=0的测试,执行顺序取决于它们在文件里定义的先后,不是随机
示例:
立即学习“Python免费学习笔记(深入)”;
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
@pytest.mark.run(order=-1)
def test_setup():
pass
<p>def test_main(): # implicit order=0
pass</p><p>@pytest.mark.run(order=1)
def test_cleanup():
pass
执行顺序是:test_setup → test_main → test_cleanup(不是 -1 → 0 → 1 数值顺序,而是分组后组内保持原序)。
替代方案:用 pytest_collection_modifyitems 真正接管顺序
如果确实需要按命名规则、标签组合、甚至外部配置文件决定顺序,直接 hook 收集结果更可靠,且兼容参数化和 fixture。
- 在
conftest.py中实现pytest_collection_modifyitems - 遍历
items列表,用item.name或item.get_closest_marker("priority")提取排序依据 - 调用
items.sort(key=...),注意 key 函数必须稳定(避免同一测试多次运行顺序不同) - 不要在排序逻辑里调用
item.own_markers以外的运行时属性,此时 fixture 尚未 setup
简单示例(按测试名后缀数字排序):
def pytest_collection_modifyitems(items):
items.sort(key=lambda x: int(x.name.split("_")[-1]) if x.name.endswith(tuple(str(i) for i in range(10))) else 999)
真正可控的顺序控制得绕过插件,直接干预 pytest 的 collection 流程;而 pytest-ordering 更适合“少量关键测试微调先后”的场景,别指望它撑起整套流程编排。

















