如何用pytest-order实现test A→test B→test A的测试执行顺序?
你遇到的核心问题是:pytest默认每个测试函数仅收集执行一次,pytest-order只能控制现有测试项的执行顺序,无法让同一个测试函数重复执行。之前给test_b加多个order标记的做法无效,因为pytest-order只会识别该测试函数的一个order标记(你这里取了order(1)),而且也无法让测试重复运行。
以下两种方案可以实现你需要的test A → test B → test A执行顺序:
方案一:封装公共测试逻辑,拆分测试入口(简单直观)
把test_a的核心逻辑封装成普通函数,再写两个独立的测试函数分别调用它,配合pytest-order标记顺序:
import logging import pytest def _test_a_logic(): logging.info('test_a') pass @pytest.mark.order(1) def test_a_first(): _test_a_logic() @pytest.mark.order(2) def test_b(): logging.info('test_b') pass @pytest.mark.order(3) def test_a_second(): _test_a_logic()
执行后会按顺序运行test_a_first→test_b→test_a_second,实际效果就是test_a的逻辑执行两次,中间夹着test_b。
方案二:使用pytest钩子复制测试项(无需修改原测试函数)
如果不想修改原测试函数的结构,可以在项目根目录创建conftest.py,通过pytest_collection_modifyitems钩子复制test_a的测试项,然后重新排序:
# conftest.py def pytest_collection_modifyitems(items): # 找到目标测试项 test_a = None test_b = None for item in items: if item.name == "test_a": test_a = item elif item.name == "test_b": test_b = item if test_a and test_b: # 清空原有测试项列表,按指定顺序重新添加 items.clear() items.append(test_a) items.append(test_b) # 复制test_a的测试项,修改名称避免重复冲突 test_a_copy = test_a.copy() test_a_copy.name = f"{test_a.name}_second_run" test_a_copy._nodeid = f"{test_a._nodeid}::second_run" items.append(test_a_copy)
原测试代码保持不变:
import logging import pytest def test_a(): logging.info('test_a') pass def test_b(): logging.info('test_b') pass
执行后会收集到3个测试项,顺序为test_a→test_b→test_a_second_run,实现test_a两次执行的需求。
验证执行效果
两种方案执行后都会得到类似如下的输出:
=================== 测试会话开始 ==================
收集测试用例... 已收集3个测试项
test.py::test_a_first 已通过 [ 33%]
test.py::test_b 已通过 [ 66%]
test.py::test_a_second 已通过 [100%]
=================== 3个测试用例通过,耗时0.07s ===================
(方案二的输出中测试项名称会是test_a、test_b、test_a_second_run)
内容的提问来源于stack exchange,提问作者dubaksk

