Address review

This commit is contained in:
baekdohyeop
2021-11-29 02:49:50 +09:00
parent 1b5d6b6db7
commit 62e50d0097
6 changed files with 65 additions and 38 deletions

View File

@@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -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

View File

@@ -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``.

View File

@@ -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."
),
)
@@ -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)

View File

@@ -120,14 +120,14 @@ class WorkerInteractor:
# 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:
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
@@ -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"

View File

@@ -3,22 +3,10 @@ from py.log import Producer
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):
@@ -49,10 +37,9 @@ class LoadGroupScheduling(LoadScopeScheduling):
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

View File

@@ -1331,7 +1331,7 @@ class TestGroupScope:
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
@@ -1371,12 +1371,12 @@ class TestGroupScope:
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
@@ -1414,7 +1414,7 @@ class TestGroupScope:
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
"""
@@ -1422,7 +1422,7 @@ class TestGroupScope:
import pytest
def test_1():
pass
@pytest.mark.xgroup(name="xgroup")
@pytest.mark.xdist_group(name="xdist_group")
def test_2():
pass
"""
@@ -1434,6 +1434,25 @@ class TestGroupScope:
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 = """