pytest使用--dist=loadfile/loadscope时如何控制测试分配及指定测试末尾执行
pytest分布式执行下指定worker内测试最后运行的解决方案
问题核心原因
原生@pytest.mark.last仅在单进程执行场景生效,pytest-xdist分布式调度模式下,每个worker会独立调度自身分配到的测试用例,last标记不会保证在worker本地测试队列中排在末尾,提前运行时就会阻塞同worker剩余测试的执行,触发死循环。
方案1:调整worker本地测试执行顺序(最适配当前场景)
通过pytest内置的pytest_collection_modifyitems钩子,在每个worker的测试收集阶段,将带last标记的用例挪到当前worker分配到的所有测试的末尾,即可实现单worker内部该测试最后执行的需求。
将以下代码放入项目根目录的conftest.py中即可生效:
def pytest_collection_modifyitems(config, items): # 仅在xdist worker节点执行顺序调整逻辑,不影响master节点 if not hasattr(config, "workerinput"): return last_test_items = [] normal_test_items = [] for item in items: if item.get_closest_marker("last"): last_test_items.append(item) else: normal_test_items.append(item) # 重组测试队列,last标记用例放到队列末尾 items[:] = normal_test_items + last_test_items
该逻辑不会修改你原有--dist=loadfile/loadscope的测试分配规则,也不会影响其他worker的调度逻辑,特殊测试运行时同worker分配的所有测试已经全部执行完成,不会再出现死循环问题。
方案2:固定特殊测试模块分配规则(可选补充)
如果要避免tests_b.py被随机分配到不同worker的不确定性,可以自定义xdist的调度逻辑,固定tests_b.py的分配目标,示例代码如下:
from xdist.scheduler import LoadFileScheduling class CustomTestScheduler(LoadFileScheduling): def assign_work(self): # 优先将tests_b.py的测试固定分配给第一个worker b_file_tests = [] other_tests = [] for test in self.test_collection: if "tests_b.py" in test: b_file_tests.append(test) else: other_tests.append(test) self.test_collection = other_tests + b_file_tests super().assign_work() def pytest_xdist_make_scheduler(config, log): return CustomTestScheduler(config, log)
注意事项
原有等待其他worker执行完成的校验逻辑可以正常保留,和上述调整没有冲突。
内容的提问来源于stack exchange,提问作者Narendra Babu
相关产品推荐
相关产品推荐

