Skip to content

Commit

Permalink
Address review
Browse files Browse the repository at this point in the history
  • Loading branch information
baekdohyeop committed Nov 28, 2021
1 parent 1b5d6b6 commit 62e50d0
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 38 deletions.
22 changes: 22 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ distribution algorithm this with the ``--dist`` option. It takes these values:
distributed to available workers as whole units. This guarantees that all
tests in a file run in the same worker.

* ``--dist loadgroup``: Tests are grouped by xdist_group mark. Groups are
distributed to available workers as whole units. This guarantees that all
tests with same xdist_group name run in the same worker.

Making session-scoped fixtures execute only once
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -414,3 +418,21 @@ where the configuration file was found.
.. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist
.. _`pytest-xdist repository`: https://github.com/pytest-dev/pytest-xdist
.. _`pytest`: http://pytest.org

Groups tests by xdist_group mark
---------------------------------

*New in version 2.4.*

Two or more tests belonging to different classes or modules can be executed in same worker through the xdist_group marker:

.. code-block:: python
@pytest.mark.xdist_group(name="group1")
def test1():
pass
class TestA:
@pytest.mark.xdist_group("group1")
def test2():
pass
2 changes: 1 addition & 1 deletion changelog/733.feature.rst
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Create new dist option 'loadgroup'
New ``--dist=loadgroup`` option, which ensures all tests marked with ``@pytest.mark.xdist_group`` run in the same session/worker. Other tests run distributed as in ``--dist=load``.
5 changes: 2 additions & 3 deletions src/xdist/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ def pytest_addoption(parser):
" the same scope to any available environment.\n\n"
"loadfile: load balance by sending test grouped by file"
" to any available environment.\n\n"
"loadgroup: load balance by sending any pending test or test group"
" to any available enviroment.\n\n"
"loadgroup: like load, but sends tests marked with 'xdist_group' to the same worker.\n\n"
"(default) no: run tests inprocess, don't distribute."
),
)
Expand Down Expand Up @@ -207,7 +206,7 @@ def pytest_configure(config):
config.option.forked = True

config_line = (
"xgroup: specify group for tests should run in same session."
"xdist_group: specify group for tests should run in same session."
"in relation to one another. " + "Provided by pytest-xdist."
)
config.addinivalue_line("markers", config_line)
Expand Down
20 changes: 10 additions & 10 deletions src/xdist/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,15 @@ def pytest_collection_modifyitems(self, session, config, items):
# add the group name to nodeid as suffix if --dist=loadgroup
if config.getvalue("loadgroup"):
for item in items:
try:
mark = item.get_closest_marker("xgroup")
except AttributeError:
mark = item.get_marker("xgroup")

if mark:
gname = mark.kwargs.get("name")
if gname:
item._nodeid = "{}@{}".format(item.nodeid, gname)
mark = item.get_closest_marker("xdist_group")
if not mark:
continue
gname = (
mark.args[0]
if len(mark.args) > 0
else mark.kwargs.get("name", "default")
)
item._nodeid = "{}@{}".format(item.nodeid, gname)

@pytest.hookimpl
def pytest_collection_finish(self, session):
Expand Down Expand Up @@ -250,7 +250,7 @@ def remote_initconfig(option_dict, args):


def setup_config(config, basetemp):
config.option.loadgroup = True if config.getvalue("dist") == "loadgroup" else False
config.option.loadgroup = config.getvalue("dist") == "loadgroup"
config.option.looponfail = False
config.option.usepdb = False
config.option.dist = "no"
Expand Down
25 changes: 6 additions & 19 deletions src/xdist/scheduler/loadgroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,10 @@


class LoadGroupScheduling(LoadScopeScheduling):
"""Implement load scheduling across nodes, but grouping test only has group mark.
"""Implement load scheduling across nodes, but grouping test by xdist_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.
This class behaves very much like LoadScopeScheduling, but it groups tests by xdist_group mark
instead of the module or class to which they belong to.
"""

def __init__(self, config, log=None):
Expand Down Expand Up @@ -49,10 +37,9 @@ def _split_scope(self, nodeid):
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::
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
Expand Down
29 changes: 24 additions & 5 deletions testing/acceptance_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,7 @@ def test_by_module(self, testdir):
test_file = """
import pytest
class TestA:
@pytest.mark.xgroup(name="xgroup")
@pytest.mark.xdist_group(name="xdist_group")
@pytest.mark.parametrize('i', range(5))
def test(self, i):
pass
Expand Down Expand Up @@ -1371,12 +1371,12 @@ def test_by_class(self, testdir):
test_a="""
import pytest
class TestA:
@pytest.mark.xgroup(name="xgroup")
@pytest.mark.xdist_group(name="xdist_group")
@pytest.mark.parametrize('i', range(10))
def test(self, i):
pass
class TestB:
@pytest.mark.xgroup(name="xgroup")
@pytest.mark.xdist_group(name="xdist_group")
@pytest.mark.parametrize('i', range(10))
def test(self, i):
pass
Expand Down Expand Up @@ -1414,15 +1414,15 @@ def test(self, i):
def test_module_single_start(self, testdir):
test_file1 = """
import pytest
@pytest.mark.xgroup(name="xgroup")
@pytest.mark.xdist_group(name="xdist_group")
def test():
pass
"""
test_file2 = """
import pytest
def test_1():
pass
@pytest.mark.xgroup(name="xgroup")
@pytest.mark.xdist_group(name="xdist_group")
def test_2():
pass
"""
Expand All @@ -1434,6 +1434,25 @@ def test_2():

assert a.keys() == b.keys() and b.keys() == c.keys()

def test_with_two_group_names(self, testdir):
test_file = """
import pytest
@pytest.mark.xdist_group(name="group1")
def test_1():
pass
@pytest.mark.xdist_group("group2")
def test_2():
pass
"""
testdir.makepyfile(test_a=test_file, test_b=test_file)
result = testdir.runpytest("-n2", "--dist=loadgroup", "-v")
a_1 = get_workers_and_test_count_by_prefix("test_a.py::test_1", result.outlines)
a_2 = get_workers_and_test_count_by_prefix("test_a.py::test_2", result.outlines)
b_1 = get_workers_and_test_count_by_prefix("test_b.py::test_1", result.outlines)
b_2 = get_workers_and_test_count_by_prefix("test_b.py::test_2", result.outlines)

assert a_1.keys() == b_1.keys() and a_2.keys() == b_2.keys()


class TestLocking:
_test_content = """
Expand Down

0 comments on commit 62e50d0

Please sign in to comment.