Create new dist option 'loadgroup'

This commit is contained in:
baekdohyeop
2021-11-29 00:03:49 +09:00
parent 6d83034bb8
commit 52a395888f
6 changed files with 203 additions and 1 deletions

View File

@@ -2,3 +2,4 @@ from xdist.scheduler.each import EachScheduling # noqa
from xdist.scheduler.load import LoadScheduling # noqa
from xdist.scheduler.loadfile import LoadFileScheduling # noqa
from xdist.scheduler.loadscope import LoadScopeScheduling # noqa
from xdist.scheduler.loadgroup import LoadGroupScheduling # noqa

View File

@@ -0,0 +1,67 @@
from .loadscope import LoadScopeScheduling
from py.log import Producer
class LoadGroupScheduling(LoadScopeScheduling):
"""Implement load scheduling across nodes, but grouping test only has group mark.
This 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 group mark
(If there is no group mark, it is itself a group.), and those work units
et submitted to nodes. Whenever a node finishes an item, it calls
``.mark_test_complete()`` which will trigger the scheduler to assign more
work units if the number of pending tests for the node falls below a low-watermark.
When created, ``numnodes`` defines how many nodes are expected to submit a
collection. This is used to know when all nodes have finished collection.
This class behaves very much like LoadScopeScheduling,
but with a itself or group(by marked) scope.
"""
def __init__(self, config, log=None):
super().__init__(config, log)
if log is None:
self.log = Producer("loadgroupsched")
else:
self.log = log.loadgroupsched
def _split_scope(self, nodeid):
"""Determine the scope (grouping) of a nodeid.
There are usually 3 cases for a nodeid::
example/loadsuite/test/test_beta.py::test_beta0
example/loadsuite/test/test_delta.py::Delta1::test_delta0
example/loadsuite/epsilon/__init__.py::epsilon.epsilon
#. Function in a test module.
#. Method of a class in a test module.
#. Doctest in a function in a package.
With loadgroup, two cases are added::
example/loadsuite/test/test_beta.py::test_beta0
example/loadsuite/test/test_delta.py::Delta1::test_delta0
example/loadsuite/epsilon/__init__.py::epsilon.epsilon
example/loadsuite/test/test_gamma.py::test_beta0@gname
example/loadsuite/test/test_delta.py::Gamma1::test_gamma0@gname
This function will group tests with the scope determined by splitting
the first ``@`` from the right. That is, test will be grouped in a
single work unit when they have same group name.
In the above example, scopes will be::
example/loadsuite/test/test_beta.py::test_beta0
example/loadsuite/test/test_delta.py::Delta1::test_delta0
example/loadsuite/epsilon/__init__.py::epsilon.epsilon
gname
gname
"""
if nodeid.rfind("@") > nodeid.rfind("]"):
# check the index of ']' to avoid the case: parametrize mark value has '@'
return nodeid.split("@")[-1]
else:
return nodeid