Skip to content

Commit ba83984

Browse files
smarieSylvain MARIEZac-HDnicoddemus
authored
New methods is_xdist_worker, is_xdist_master, get_xdist_worker_id. (#505)
Co-authored-by: Sylvain MARIE <[email protected]> Co-authored-by: Zac Hatfield-Dodds <[email protected]> Co-authored-by: Bruno Oliveira <[email protected]>
1 parent abc1ae0 commit ba83984

File tree

5 files changed

+108
-7
lines changed

5 files changed

+108
-7
lines changed

README.rst

+29-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ a test or fixture, you may use the ``worker_id`` fixture to do so:
268268
When ``xdist`` is disabled (running with ``-n0`` for example), then
269269
``worker_id`` will return ``"master"``.
270270

271-
Additionally, worker processes have the following environment variables
271+
Worker processes also have the following environment variables
272272
defined:
273273

274274
* ``PYTEST_XDIST_WORKER``: the name of the worker, e.g., ``"gw2"``.
@@ -278,6 +278,34 @@ defined:
278278
The information about the worker_id in a test is stored in the ``TestReport`` as
279279
well, under the ``worker_id`` attribute.
280280

281+
Since version 2.0, the following functions are also available in the ``xdist`` module:
282+
283+
.. code-block:: python
284+
285+
def is_xdist_worker(request_or_session) -> bool:
286+
"""Return `True` if this is an xdist worker, `False` otherwise
287+
288+
:param request_or_session: the `pytest` `request` or `session` object
289+
"""
290+
291+
def is_xdist_master(request_or_session) -> bool:
292+
"""Return `True` if this is the xdist master, `False` otherwise
293+
294+
Note: this method also returns `False` when distribution has not been
295+
activated at all.
296+
297+
:param request_or_session: the `pytest` `request` or `session` object
298+
"""
299+
300+
def get_xdist_worker_id(request_or_session) -> str:
301+
"""Return the id of the current worker ('gw0', 'gw1', etc) or 'master'
302+
if running on the 'master' node.
303+
304+
If not distributing tests (for example passing `-n0` or not passing `-n` at all) also return 'master'.
305+
306+
:param request_or_session: the `pytest` `request` or `session` object
307+
"""
308+
281309
282310
Uniquely identifying the current test run
283311
-----------------------------------------

changelog/504.feature.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
New functions ``xdist.is_xdist_worker``, ``xdist.is_xdist_master``, ``xdist.get_xdist_worker_id``, to easily identify the current node.

src/xdist/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from xdist.plugin import is_xdist_worker, is_xdist_master, get_xdist_worker_id
12
from xdist._version import version as __version__
23

3-
__all__ = ["__version__"]
4+
__all__ = ["__version__", "is_xdist_worker", "is_xdist_master", "get_xdist_worker_id"]

src/xdist/plugin.py

+39-5
Original file line numberDiff line numberDiff line change
@@ -192,19 +192,53 @@ def pytest_cmdline_main(config):
192192

193193

194194
# -------------------------------------------------------------------------
195-
# fixtures
195+
# fixtures and API to easily know the role of current node
196196
# -------------------------------------------------------------------------
197197

198198

199+
def is_xdist_worker(request_or_session) -> bool:
200+
"""Return `True` if this is an xdist worker, `False` otherwise
201+
202+
:param request_or_session: the `pytest` `request` or `session` object
203+
"""
204+
return hasattr(request_or_session.config, "workerinput")
205+
206+
207+
def is_xdist_master(request_or_session) -> bool:
208+
"""Return `True` if this is the xdist master, `False` otherwise
209+
210+
Note: this method also returns `False` when distribution has not been
211+
activated at all.
212+
213+
:param request_or_session: the `pytest` `request` or `session` object
214+
"""
215+
return (
216+
not is_xdist_worker(request_or_session)
217+
and request_or_session.config.option.dist != "no"
218+
)
219+
220+
221+
def get_xdist_worker_id(request_or_session) -> str:
222+
"""Return the id of the current worker ('gw0', 'gw1', etc) or 'master'
223+
if running on the 'master' node.
224+
225+
If not distributing tests (for example passing `-n0` or not passing `-n` at all)
226+
also return 'master'.
227+
228+
:param request_or_session: the `pytest` `request` or `session` object
229+
"""
230+
if hasattr(request_or_session.config, "workerinput"):
231+
return request_or_session.config.workerinput["workerid"]
232+
else:
233+
return "master"
234+
235+
199236
@pytest.fixture(scope="session")
200237
def worker_id(request):
201238
"""Return the id of the current worker ('gw0', 'gw1', etc) or 'master'
202239
if running on the master node.
203240
"""
204-
if hasattr(request.config, "workerinput"):
205-
return request.config.workerinput["workerid"]
206-
else:
207-
return "master"
241+
return get_xdist_worker_id(request)
208242

209243

210244
@pytest.fixture(scope="session")

testing/acceptance_test.py

+37
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import py
55
import pytest
6+
import xdist
67

78

89
class TestDistribution:
@@ -1366,3 +1367,39 @@ def get_workers_and_test_count_by_prefix(prefix, lines, expected_status="PASSED"
13661367
if expected_status == status and nodeid.startswith(prefix):
13671368
result[worker] = result.get(worker, 0) + 1
13681369
return result
1370+
1371+
1372+
class TestAPI:
1373+
@pytest.fixture
1374+
def fake_request(self):
1375+
class FakeOption:
1376+
def __init__(self):
1377+
self.dist = "load"
1378+
1379+
class FakeConfig:
1380+
def __init__(self):
1381+
self.workerinput = {"workerid": "gw5"}
1382+
self.option = FakeOption()
1383+
1384+
class FakeRequest:
1385+
def __init__(self):
1386+
self.config = FakeConfig()
1387+
1388+
return FakeRequest()
1389+
1390+
def test_is_xdist_worker(self, fake_request):
1391+
assert xdist.is_xdist_worker(fake_request)
1392+
del fake_request.config.workerinput
1393+
assert not xdist.is_xdist_worker(fake_request)
1394+
1395+
def test_is_xdist_master(self, fake_request):
1396+
assert not xdist.is_xdist_master(fake_request)
1397+
del fake_request.config.workerinput
1398+
assert xdist.is_xdist_master(fake_request)
1399+
fake_request.config.option.dist = "no"
1400+
assert not xdist.is_xdist_master(fake_request)
1401+
1402+
def test_get_xdist_worker_id(self, fake_request):
1403+
assert xdist.get_xdist_worker_id(fake_request) == "gw5"
1404+
del fake_request.config.workerinput
1405+
assert xdist.get_xdist_worker_id(fake_request) == "master"

0 commit comments

Comments
 (0)