使用pytest动态控制测试顺序
Dynamically control order of tests with pytest
我想使用逻辑来控制我的测试顺序,该逻辑将在它们已经 运行ning 时动态重新排序它们。
我的用例是这样的:我正在使用 xdist 并行化我的测试,并且每个测试都使用来自公共和有限池的外部资源。一些测试比其他测试使用更多的资源,因此在任何给定时间,当只有一小部分资源可用时,一些测试拥有它们需要的资源 运行 而其他测试则没有。
我想优化资源的使用,所以我想根据当前可用的资源动态选择 运行 接下来要进行的测试。我会在收集阶段计算一个最优排序,但我事先不知道每次测试需要多长时间,所以我无法预测哪些资源在什么时候可用。
我还没有找到用插件实现此行为的方法,因为收集阶段似乎与 运行ning 阶段不同,而且我不知道另一种修改列表的方法测试 运行 除了收集挂钩。
非常感谢任何建议,无论是实施此方法的方法还是优化资源利用率的替代想法。我的替代方案是编写我自己的简单测试 运行ner,但我不想放弃 pytest 提供的其余部分。
谢谢!
不是您问题的完整答案,而是您关于 pytest 的问题的完整答案,以及一些提示。
要更改 pytest 中的测试顺序(只是 pytest,而不是 pytest-xdist),您可以通过安装此钩子包装器随时更改测试项的顺序:
conftest.py
:
import pytest
import random
random.seed()
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_protocol(item, nextitem):
yield
idx = item.session.items.index(item)
remaining = item.session.items[idx+1:]
random.shuffle(remaining)
item.session.items[idx+1:] = remaining
更改已执行的内容没有意义,只能更改剩余的内容 — 因此,[idx+1:]
。在这个例子中,我只是打乱了项目,但你可以用剩下的特征列表做任何你想做的事。
请记住:这会影响装置的设置和拆卸方式(范围在 'function' 以上的装置)。最初,pytest 对测试进行排序,以便他们可以以最有效的方式利用固定装置。具体来说,nextitem
参数在内部用于跟踪 fixture 是否应该完成。由于您每次都有效地更改它,因此效果可能无法预测。
有了pytest-xdist,一切就完全不同了。您必须继续阅读 how pytest-dist distributes the tests across the slaves。
首先,每个奴隶收集所有相同的测试,并且完全按照相同的顺序。如果顺序不同,pytest-xdist 将失败。所以你不能在 collection.
重新排序
其次,主进程发送该收集列表中的测试索引作为下一个要执行的测试。所以,collection必须一直不变。
第三,你可以在pytest-xdist本身重新定义pytest_xdist_make_scheduler
hook. There are few sample implementations。您可以使用节点 added/removed 和通过相应方法收集的测试,在 schedule()
方法中定义自己的测试调度逻辑。
第四,那太容易了。 .schedule()
方法仅在 slave_collectionfinish
从从机发送的事件中调用。这么说我很难过,但是您必须始终终止并重新启动从属进程才能触发此事件,并 re-schedule 剩余的测试。
如您所见,pytest-xdist 的实施将非常庞大且复杂。但我希望这会给您一些提示。
我想使用逻辑来控制我的测试顺序,该逻辑将在它们已经 运行ning 时动态重新排序它们。
我的用例是这样的:我正在使用 xdist 并行化我的测试,并且每个测试都使用来自公共和有限池的外部资源。一些测试比其他测试使用更多的资源,因此在任何给定时间,当只有一小部分资源可用时,一些测试拥有它们需要的资源 运行 而其他测试则没有。
我想优化资源的使用,所以我想根据当前可用的资源动态选择 运行 接下来要进行的测试。我会在收集阶段计算一个最优排序,但我事先不知道每次测试需要多长时间,所以我无法预测哪些资源在什么时候可用。
我还没有找到用插件实现此行为的方法,因为收集阶段似乎与 运行ning 阶段不同,而且我不知道另一种修改列表的方法测试 运行 除了收集挂钩。
非常感谢任何建议,无论是实施此方法的方法还是优化资源利用率的替代想法。我的替代方案是编写我自己的简单测试 运行ner,但我不想放弃 pytest 提供的其余部分。
谢谢!
不是您问题的完整答案,而是您关于 pytest 的问题的完整答案,以及一些提示。
要更改 pytest 中的测试顺序(只是 pytest,而不是 pytest-xdist),您可以通过安装此钩子包装器随时更改测试项的顺序:
conftest.py
:
import pytest
import random
random.seed()
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_protocol(item, nextitem):
yield
idx = item.session.items.index(item)
remaining = item.session.items[idx+1:]
random.shuffle(remaining)
item.session.items[idx+1:] = remaining
更改已执行的内容没有意义,只能更改剩余的内容 — 因此,[idx+1:]
。在这个例子中,我只是打乱了项目,但你可以用剩下的特征列表做任何你想做的事。
请记住:这会影响装置的设置和拆卸方式(范围在 'function' 以上的装置)。最初,pytest 对测试进行排序,以便他们可以以最有效的方式利用固定装置。具体来说,nextitem
参数在内部用于跟踪 fixture 是否应该完成。由于您每次都有效地更改它,因此效果可能无法预测。
有了pytest-xdist,一切就完全不同了。您必须继续阅读 how pytest-dist distributes the tests across the slaves。
首先,每个奴隶收集所有相同的测试,并且完全按照相同的顺序。如果顺序不同,pytest-xdist 将失败。所以你不能在 collection.
重新排序其次,主进程发送该收集列表中的测试索引作为下一个要执行的测试。所以,collection必须一直不变。
第三,你可以在pytest-xdist本身重新定义pytest_xdist_make_scheduler
hook. There are few sample implementations。您可以使用节点 added/removed 和通过相应方法收集的测试,在 schedule()
方法中定义自己的测试调度逻辑。
第四,那太容易了。 .schedule()
方法仅在 slave_collectionfinish
从从机发送的事件中调用。这么说我很难过,但是您必须始终终止并重新启动从属进程才能触发此事件,并 re-schedule 剩余的测试。
如您所见,pytest-xdist 的实施将非常庞大且复杂。但我希望这会给您一些提示。