我有以下目录布局:
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 and 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,))
答案 0 :(得分:12)
使用pytest-xdist,目前没有“per-file”或“per-test-suite”发行版。实际上,如果每个文件的分发(例如,文件中的测试一次只能由一个工作人员执行)将对您的用例有所帮助,我建议您在{{3}向pytest问题跟踪器提交功能问题并在此处链接回你的好解释。
欢呼声,霍尔格
答案 1 :(得分:4)
您可以使用--dist=loadscope
将所有测试归为同一测试类。这是pytest-xdist on pypi
默认情况下,-n选项会将挂起的测试发送到任何可用的工作程序,而没有任何保证的顺序,但是您可以使用以下选项进行控制:
--dist=loadscope
:对于测试功能,将按模块对测试进行分组,对于测试方法,将按类对测试进行分组,然后将每个组发送给可用的工作程序,以确保组中的所有测试都在同一过程中运行。如果您有昂贵的模块级或类级灯具,这将很有用。目前无法自定义分组,按类别分组优先于按模块分组。此功能是在1.19版中添加的。
--dist=loadfile
:测试将按文件名分组,然后发送到可用的工作程序,以确保组中的所有测试都在同一工作程序中运行。此功能是在1.21版中添加的。
答案 2 :(得分:1)
是的,有这样的方法,每个xdist版本1.28.0
的可用选项如下:
--dist=each
:将所有测试发送到所有节点,因此每个测试都在每个节点上运行。--dist=load
:在所有节点上分布收集的测试,因此每个测试
只运行一次。所有节点都收集并提交测试套件,并且
当收到(测试套件)的所有集合时,将验证它们是
相同的集合。然后集合被分成
块和块被提交给节点以执行。--dist=loadscope
在所有节点上分布收集的测试,以便运行每个测试
就一次。所有节点都收集并提交测试列表,以及所有
收到集合后,请确保它们是相同的集合。
然后将集合按工作单元划分,按测试范围分组,
这些工作单元将被提交到节点。--dist=loadfile
在所有节点上分布收集的测试,以便运行每个测试
就一次。所有节点都收集并提交测试列表,以及所有
收到集合后,请确保它们是相同的集合。
然后将集合按工作单元划分,按测试文件分组,
这些工作单元将被提交到节点。如果您需要其他任何信息,建议您直接进入actual implementation of the schedulers,并查看分发的完成情况。
答案 3 :(得分:1)
pytest_mproc(https://nak.github.io/pytest_mproc_docs/index.html)提供了一个“组”修饰符,使您可以将测试分组在一起以按顺序执行。与xdist相比,它在处理大量内核时具有更快的启动时间,并提供“全局”范围测试夹具。
答案 4 :(得分:0)
像问题中的目录一样具有测试套件,您可以通过以下方式并行运行它们:
pytest -n=$(ls **/test*py | wc -l) --dist=loadfile
如果您的测试套件文件位于单个目录中,那么
pytest -n=$(ls test*py | wc -l) --dist=loadfile
如果出现新的套件文件,它将自动包含新的测试文件,并为其添加其他工作程序
答案 5 :(得分:0)
可能还值得注意的是,pytest-xdist github 上的 this issue 解决了我认为您在这里询问的用例。
由于该问题尚未解决(尽管已在 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 而不是文件类型来拆分组。它对我有用,但我不能保证健壮性,因为我们正在修补一些正常的内部代码;使用风险自负。