有没有办法控制 pytest-xdist 如何并行运行测试?

发布于 2024-10-11 05:20:57 字数 1816 浏览 2 评论 0原文

我有以下目录布局:

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

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

import pytest 
class testsomething:
      def setup_class(self):
          ''' do some setup '''
          # Do some setup stuff here      
      def teardown_class(self):
          '''' do some teardown'''
          # Do some teardown stuff here

      def test1(self):
          # Do some test1 related stuff

      def test2(self):
          # Do some test2 related stuff

      ....
      ....
      ....
      def test40(self):
          # Do some test40 related stuff

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

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

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

本质上我希望执行的样子是:

worker1: executes all tests in testsuite1.py serially
worker2: executes all tests in testsuite2.py serially
worker3: executes all tests in testsuite3.py serially
worker4: executes all tests in testsuite4.py serially

worker1、worker2、worker3 和worker4都是并行执行的。

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

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

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

if __name__=='__main__':
   #Gather all the testsuite names
   for each testsuite:
       multiprocessing.Process(test_execute_func,(testsuite_path,))

I have the following directory layout:

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

The format of testsuite*.py modules is as follows:

import pytest 
class testsomething:
      def setup_class(self):
          ''' do some setup '''
          # Do some setup stuff here      
      def teardown_class(self):
          '''' do some teardown'''
          # Do some teardown stuff here

      def test1(self):
          # Do some test1 related stuff

      def test2(self):
          # Do some test2 related stuff

      ....
      ....
      ....
      def test40(self):
          # Do some test40 related stuff

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

The problem I have is that I would like to execute the 'testsuites' in parallel i.e. I want testsuite1, testsuite2, testsuite3 and testsuite4 to start execution in parallel but individual tests within the testsuites need to be executed serially.

When I use the 'xdist' plugin from py.test and kick off the tests using 'py.test -n 4', py.test is gathering all the tests and randomly load balancing the tests among 4 workers. This leads to the 'setup_class' method to be executed every time of each test within a 'testsuitex.py' module (which defeats my purpose. I want setup_class to be executed only once per class and tests executed serially there after).

Essentially what I want the execution to look like is:

worker1: executes all tests in testsuite1.py serially
worker2: executes all tests in testsuite2.py serially
worker3: executes all tests in testsuite3.py serially
worker4: executes all tests in testsuite4.py serially

while worker1, worker2, worker3 and worker4 are all executed in parallel.

Is there a way to achieve this in 'pytest-xidst' framework?

The only option that I can think of is to kick off different processes to execute each test suite individually within runner.py:


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

if __name__=='__main__':
   #Gather all the testsuite names
   for each testsuite:
       multiprocessing.Process(test_execute_func,(testsuite_path,))

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

云之铃。 2024-10-18 05:20:57

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

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

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

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

You can use --dist=loadscope to group all the tests in the same test class. Here is the doc from pytest-xdist on pypi

By default, the -n option will send pending tests to any worker that is available, without any guaranteed order, but you can control this with these options:

--dist=loadscope: tests will be grouped by module for test functions and by class for test methods, then each group will be sent to an available worker, guaranteeing that all tests in a group run in the same process. This can be useful if you have expensive module-level or class-level fixtures. Currently the groupings can’t be customized, with grouping by class takes priority over grouping by module. This feature was added in version 1.19.

--dist=loadfile: tests will be grouped by file name, and then will be sent to an available worker, guaranteeing that all tests in a group run in the same worker. This feature was added in version 1.21.

够运 2024-10-18 05:20:57

多个选项可用 是

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

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

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

Multiple Options Available

Yes, there are such ways, the available options per xdist version 1.28.0 is the following ones:

  • --dist=each: Sends all the tests to all the nodes, so each test is run on every node.
  • --dist=load: Distributes the tests collected across all nodes so each test
    is run just once. All nodes collect and submit the test suite and
    when all collections (of test suites) are received it is verified they are
    identical collections. Then the collection gets divided up in
    chunks and chunks get submitted to nodes for execution.
  • --dist=loadscope Distributes the tests collected across all nodes so each test is run
    just once. All nodes collect and submit the list of tests and when all
    collections are received it is verified they are identical collections.
    Then the collection gets divided up in work units, grouped by test scope,
    and those work units get submitted to nodes.
  • --dist=loadfile Distributes the tests collected across all nodes so each test is run
    just once. All nodes collect and submit the list of tests and when all
    collections are received it is verified they are identical collections.
    Then the collection gets divided up in work units, grouped by test file,
    and those work units get submitted to nodes.

If you need any further information I recommend you to go straightly into the actual implementation of the schedulers and checkout how the distribution is being done.

盗心人 2024-10-18 05:20:57

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

干杯,霍尔格

With pytest-xdist there currently no kind of "per-file" or "per-test-suite" distribution. Actually, if a per-file distribution (e.g. tests in a file will be only executed by at most one worker at a time) would already help your use case i encourage you to file a feature issue with the pytest issue tracker at https://bitbucket.org/hpk42/pytest/issues?status=new&status=open and link back to your good explanation here.

cheers,holger

红衣飘飘貌似仙 2024-10-18 05:20:57

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

pytest_mproc (https://nak.github.io/pytest_mproc_docs/index.html) provides a "group" decorator that allows you to group tests together for execution serially. It also has faster startup time when working on large numbers of cores than xdist and provides a "global" scope test fixture.

维持三分热 2024-10-18 05:20:57

将测试套件放在像问题一样的目录中,您可以通过以下方式并行运行它们:

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

如果您的测试套件文件位于单个目录中,那么万一

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

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

Having test suites in directory like in the question, you can run them in parallel it via:

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

If you have your tests suite files in single directory then just

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

In case new suite file occurs, this will include new test file automatically and will add additional worker for it

命硬 2024-10-18 05:20:57

还值得注意的是 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 函数,以按节点 ID 而不是按文件类型分割组。它对我有用,但我无法保证稳健性,因为我们正在对一些通常的内部代码进行猴子修补;使用风险由您自行承担。

It may also be worth noting that this issue on the pytest-xdist github addresses the use case I think you're asking about here.

Since the issue hasn't yet been resolved (despite being opened in 2015), I just monkey-patched a workable solution for my specific case. In my conftest.py, I added this chunk of code:

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

It basically just overwrites the _split_scope function from xdist to split groups by the nodeid instead of by the filetype. It worked for me, but I can't guarentee robustness since we're monkey-patching some normally internal code; use at your own risk.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文