46

我有以下目录布局:

runner.py
lib/
tests/
      testsuite1/
                 testsuite1.py
      testsuite2/
                 testsuite2.py
      testsuite3/
                 testsuite3.py
      testsuite4/
                 testsuite4.py

testsuite*.py 模块的格式如下:

导入pytest
类测试东西:
      def setup_class(self):
          '''做一些设置'''
          # 在这里做一些设置      
      def teardown_class(self):
          ''''做一些拆解'''
          # 在这里做一些拆解的东西

      def test1(自我):
          # 做一些与 test1 相关的事情

      def test2(自我):
          # 做一些与 test2 相关的事情

      ……
      ……
      ……
      def test40(自我):
          # 做一些与 test40 相关的事情

如果 __name__=='__main()__'
   pytest.main(args=[os.path.abspath(__file__)])

我遇到的问题是我想并行执行“测试套件”,即我希望 testsuite1、testsuite2、testsuite3 和 testsuite4 开始并行执行,但测试套件中的各个测试需要串行执行。

当我使用 py.test 中的“xdist”插件并使用“py.test -n 4”启动测试时,py.test 正在收集所有测试并在 4 个工作人员之间随机负载平衡测试。这导致在“testsuitex.py”模块中每次测试时都要执行“setup_class”方法(这违背了我的目的。我希望每个类只执行一次 setup_class 并在之后连续执行测试)。

基本上我希望执行看起来像:

worker1:串行执行 testsuite1.py 中的所有测试
worker2:串行执行 testsuite2.py 中的所有测试
worker3:串行执行 testsuite3.py 中的所有测试
worker4:串行执行 testsuite4.py 中的所有测试

while worker1, worker2, worker3 and worker4 都是并行执行的。

有没有办法在“pytest-xidst”框架中实现这一点?

我能想到的唯一选择是启动不同的进程以在 runner.py 中单独执行每个测试套件:

def test_execute_func(testsuite_path):
    subprocess.process('py.test %s' % testsuite_path)

如果 __name__=='__main__':
   #收集所有测试套件名称
   对于每个测试套件:
       multiprocessing.Process(test_execute_func,(testsuite_path,))
4

6 回答 6

25

您可以使用--dist=loadscope将所有测试分组到同一个测试类中。这是pypi 上 pytest-xdist的文档

默认情况下, -n 选项会将待处理的测试发送给任何可用的工作人员,没有任何保证的顺序,但您可以使用以下选项进行控制:

--dist=loadscope: 测试将按模块分组测试功能,按类分组测试方法,然后每个组将被发送到一个可用的工作人员,保证一个组中的所有测试在同一个进程中运行。如果您有昂贵的模块级或类级设备,这将很有用。目前无法自定义分组,按类分组优先于按模块分组。此功能是在 1.19 版中添加的。

--dist=loadfile:测试将按文件名分组,然后将发送到可用的工作人员,保证组中的所有测试都在同一个工作人员中运行。此功能是在 1.21 版中添加的。

于 2019-06-06T09:59:06.027 回答
19

提供多种选择

是的,有这样的方法,每个 xdist 版本的可用选项1.28.0如下:

  • --dist=each:将所有测试发送到所有节点,因此每个测试都在每个节点上运行。
  • --dist=load:将收集到的测试分布在所有节点上,因此每个测试只运行一次。所有节点收集并提交测试套件,当收到所有(测试套件的)集合时,验证它们是相同的集合。然后集合被分成块,块被提交给节点执行。
  • --dist=loadscope将收集到的测试分布在所有节点上,以便每个测试只运行一次。所有节点收集并提交测试列表,当收到所有集合时,验证它们是相同的集合。然后将集合划分为工作单元,按测试范围分组,然后将这些工作单元提交给节点。
  • --dist=loadfile将收集到的测试分布在所有节点上,以便每个测试只运行一次。所有节点收集并提交测试列表,当收到所有集合时,验证它们是相同的集合。然后将集合划分为工作单元,按测试文件分组,然后将这些工作单元提交给节点。

如果您需要任何进一步的信息,我建议您直接进入调度程序的实际实现并检查分发是如何完成的。

于 2019-06-14T09:25:49.553 回答
14

使用 pytest-xdist 目前没有“per-file”或“per-test-suite”分发。实际上,如果按文件分发(例如,文件中的测试一次最多只能由一个工作人员执行)已经对您的用例有所帮助,我鼓励您在https:/使用 pytest 问题跟踪器提交功能问题/bitbucket.org/hpk42/pytest/issues?status=new&status=open并在此处链接回您的良好解释。

干杯,霍尔格

于 2011-01-09T13:46:31.027 回答
1

pytest_mproc ( https://nak.github.io/pytest_mproc_docs/index.html ) 提供了一个“组”装饰器,允许您将测试分组在一起以连续执行。在处理大量内核时,它的启动时间也比 xdist 更快,并提供“全局”范围测试夹具。

于 2020-04-25T02:27:35.557 回答
1

在问题中的目录中拥有测试套件,您可以通过以下方式并行运行它们:

pytest -n=$(ls **/test*py | wc -l) --dist=loadfile

如果您将测试套件文件放在单个目录中,那么只需

pytest -n=$(ls test*py | wc -l) --dist=loadfile

如果出现新的套件文件,这将自动包含新的测试文件并为其添加额外的工作人员

于 2020-03-03T10:52:03.730 回答
0

还可能值得注意的是,pytest-xdist github 上的这个问题解决了我认为您在这里询问的用例。

由于该问题尚未解决(尽管在 2015 年开放),我只是为我的具体案例修补了一个可行的解决方案。在我的 conftest.py 中,我添加了这段代码:

import xdist.scheduler as xdist_scheduler
def _split_scope(self, nodeid):
    return nodeid.rsplit("[", 1)[-1]
xdist_scheduler.loadscope.LoadScopeScheduling._split_scope = _split_scope

它基本上只是覆盖 xdist 中的 _split_scope 函数,以按 nodeid 而不是按文件类型拆分组。它对我有用,但我不能保证稳健性,因为我们正在修补一些通常的内部代码;使用风险自负。

于 2021-08-04T23:05:17.933 回答