Skip to content

Commit 74459ca

Browse files
committed
Add pytest-xdist support
Fixes #201.
1 parent fc8eb59 commit 74459ca

File tree

8 files changed

+128
-17
lines changed

8 files changed

+128
-17
lines changed

HISTORY.rst

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
History
33
-------
44

5+
* Add `pytest-xdist <https://pypi.org/project/pytest-xdist/>`__ support.
6+
Previously it only worked reliably when setting ``--randomly-seed``
7+
explicitly. When not provided, the default seed generated in workers could
8+
differ and collection would fail. Now when it is not provided, all xdist
9+
worker processes shared the same default seed generated in the master
10+
process.
11+
512
3.2.1 (2020-01-13)
613
------------------
714

requirements/py35.txt

+18-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
#
55
# requirements/compile.py
66
#
7+
apipkg==1.5 \
8+
--hash=sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6 \
9+
--hash=sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c \
10+
# via execnet
711
attrs==19.3.0 \
812
--hash=sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c \
913
--hash=sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72 \
@@ -79,6 +83,10 @@ entrypoints==0.3 \
7983
--hash=sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19 \
8084
--hash=sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451 \
8185
# via flake8
86+
execnet==1.7.1 \
87+
--hash=sha256:cacb9df31c9680ec5f95553976c4da484d407e85e41c83cb812aa014f0eddc50 \
88+
--hash=sha256:d4efd397930c46415f62f8a31388d6be4f27a91d7550eb79bc64a756e0056547 \
89+
# via pytest-xdist
8290
factory-boy==2.12.0 \
8391
--hash=sha256:728df59b372c9588b83153facf26d3d28947fc750e8e3c95cefa9bed0e6394ee \
8492
--hash=sha256:faf48d608a1735f0d0a3c9cbf536d64f9132b547dae7ba452c4d99a79e84a370 \
@@ -194,10 +202,18 @@ pyparsing==2.4.7 \
194202
--hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 \
195203
--hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b \
196204
# via packaging
205+
pytest-forked==1.1.3 \
206+
--hash=sha256:1805699ed9c9e60cb7a8179b8d4fa2b8898098e82d229b0825d8095f0f261100 \
207+
--hash=sha256:1ae25dba8ee2e56fb47311c9638f9e58552691da87e82d25b0ce0e4bf52b7d87 \
208+
# via pytest-xdist
209+
pytest-xdist==1.31.0 \
210+
--hash=sha256:0f46020d3d9619e6d17a65b5b989c1ebbb58fc7b1da8fb126d70f4bac4dfeed1 \
211+
--hash=sha256:7dc0d027d258cd0defc618fb97055fbd1002735ca7a6d17037018cf870e24011 \
212+
# via -r requirements.in
197213
pytest==5.4.1 \
198214
--hash=sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172 \
199215
--hash=sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970 \
200-
# via -r requirements.in
216+
# via -r requirements.in, pytest-forked, pytest-xdist
201217
python-dateutil==2.8.1 \
202218
--hash=sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c \
203219
--hash=sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a \
@@ -221,7 +237,7 @@ secretstorage==3.1.2 \
221237
six==1.14.0 \
222238
--hash=sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a \
223239
--hash=sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c \
224-
# via bleach, cryptography, packaging, pathlib2, python-dateutil, readme-renderer
240+
# via bleach, cryptography, packaging, pathlib2, pytest-xdist, python-dateutil, readme-renderer
225241
text-unidecode==1.3 \
226242
--hash=sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8 \
227243
--hash=sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93 \

requirements/py36.txt

+18-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
#
55
# requirements/compile.py
66
#
7+
apipkg==1.5 \
8+
--hash=sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6 \
9+
--hash=sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c \
10+
# via execnet
711
attrs==19.3.0 \
812
--hash=sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c \
913
--hash=sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72 \
@@ -79,6 +83,10 @@ entrypoints==0.3 \
7983
--hash=sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19 \
8084
--hash=sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451 \
8185
# via flake8
86+
execnet==1.7.1 \
87+
--hash=sha256:cacb9df31c9680ec5f95553976c4da484d407e85e41c83cb812aa014f0eddc50 \
88+
--hash=sha256:d4efd397930c46415f62f8a31388d6be4f27a91d7550eb79bc64a756e0056547 \
89+
# via pytest-xdist
8290
factory-boy==2.12.0 \
8391
--hash=sha256:728df59b372c9588b83153facf26d3d28947fc750e8e3c95cefa9bed0e6394ee \
8492
--hash=sha256:faf48d608a1735f0d0a3c9cbf536d64f9132b547dae7ba452c4d99a79e84a370 \
@@ -194,10 +202,18 @@ pyparsing==2.4.7 \
194202
--hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 \
195203
--hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b \
196204
# via packaging
205+
pytest-forked==1.1.3 \
206+
--hash=sha256:1805699ed9c9e60cb7a8179b8d4fa2b8898098e82d229b0825d8095f0f261100 \
207+
--hash=sha256:1ae25dba8ee2e56fb47311c9638f9e58552691da87e82d25b0ce0e4bf52b7d87 \
208+
# via pytest-xdist
209+
pytest-xdist==1.31.0 \
210+
--hash=sha256:0f46020d3d9619e6d17a65b5b989c1ebbb58fc7b1da8fb126d70f4bac4dfeed1 \
211+
--hash=sha256:7dc0d027d258cd0defc618fb97055fbd1002735ca7a6d17037018cf870e24011 \
212+
# via -r requirements.in
197213
pytest==5.4.1 \
198214
--hash=sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172 \
199215
--hash=sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970 \
200-
# via -r requirements.in
216+
# via -r requirements.in, pytest-forked, pytest-xdist
201217
python-dateutil==2.8.1 \
202218
--hash=sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c \
203219
--hash=sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a \
@@ -221,7 +237,7 @@ secretstorage==3.1.2 \
221237
six==1.14.0 \
222238
--hash=sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a \
223239
--hash=sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c \
224-
# via bleach, cryptography, packaging, python-dateutil, readme-renderer
240+
# via bleach, cryptography, packaging, pytest-xdist, python-dateutil, readme-renderer
225241
text-unidecode==1.3 \
226242
--hash=sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8 \
227243
--hash=sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93 \

requirements/py37.txt

+18-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
#
55
# requirements/compile.py
66
#
7+
apipkg==1.5 \
8+
--hash=sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6 \
9+
--hash=sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c \
10+
# via execnet
711
attrs==19.3.0 \
812
--hash=sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c \
913
--hash=sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72 \
@@ -79,6 +83,10 @@ entrypoints==0.3 \
7983
--hash=sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19 \
8084
--hash=sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451 \
8185
# via flake8
86+
execnet==1.7.1 \
87+
--hash=sha256:cacb9df31c9680ec5f95553976c4da484d407e85e41c83cb812aa014f0eddc50 \
88+
--hash=sha256:d4efd397930c46415f62f8a31388d6be4f27a91d7550eb79bc64a756e0056547 \
89+
# via pytest-xdist
8290
factory-boy==2.12.0 \
8391
--hash=sha256:728df59b372c9588b83153facf26d3d28947fc750e8e3c95cefa9bed0e6394ee \
8492
--hash=sha256:faf48d608a1735f0d0a3c9cbf536d64f9132b547dae7ba452c4d99a79e84a370 \
@@ -194,10 +202,18 @@ pyparsing==2.4.7 \
194202
--hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 \
195203
--hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b \
196204
# via packaging
205+
pytest-forked==1.1.3 \
206+
--hash=sha256:1805699ed9c9e60cb7a8179b8d4fa2b8898098e82d229b0825d8095f0f261100 \
207+
--hash=sha256:1ae25dba8ee2e56fb47311c9638f9e58552691da87e82d25b0ce0e4bf52b7d87 \
208+
# via pytest-xdist
209+
pytest-xdist==1.31.0 \
210+
--hash=sha256:0f46020d3d9619e6d17a65b5b989c1ebbb58fc7b1da8fb126d70f4bac4dfeed1 \
211+
--hash=sha256:7dc0d027d258cd0defc618fb97055fbd1002735ca7a6d17037018cf870e24011 \
212+
# via -r requirements.in
197213
pytest==5.4.1 \
198214
--hash=sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172 \
199215
--hash=sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970 \
200-
# via -r requirements.in
216+
# via -r requirements.in, pytest-forked, pytest-xdist
201217
python-dateutil==2.8.1 \
202218
--hash=sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c \
203219
--hash=sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a \
@@ -221,7 +237,7 @@ secretstorage==3.1.2 \
221237
six==1.14.0 \
222238
--hash=sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a \
223239
--hash=sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c \
224-
# via bleach, cryptography, packaging, python-dateutil, readme-renderer
240+
# via bleach, cryptography, packaging, pytest-xdist, python-dateutil, readme-renderer
225241
text-unidecode==1.3 \
226242
--hash=sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8 \
227243
--hash=sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93 \

requirements/py38.txt

+18-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
#
55
# requirements/compile.py
66
#
7+
apipkg==1.5 \
8+
--hash=sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6 \
9+
--hash=sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c \
10+
# via execnet
711
appdirs==1.4.3 \
812
--hash=sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92 \
913
--hash=sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e \
@@ -95,6 +99,10 @@ entrypoints==0.3 \
9599
--hash=sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19 \
96100
--hash=sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451 \
97101
# via flake8
102+
execnet==1.7.1 \
103+
--hash=sha256:cacb9df31c9680ec5f95553976c4da484d407e85e41c83cb812aa014f0eddc50 \
104+
--hash=sha256:d4efd397930c46415f62f8a31388d6be4f27a91d7550eb79bc64a756e0056547 \
105+
# via pytest-xdist
98106
factory-boy==2.12.0 \
99107
--hash=sha256:728df59b372c9588b83153facf26d3d28947fc750e8e3c95cefa9bed0e6394ee \
100108
--hash=sha256:faf48d608a1735f0d0a3c9cbf536d64f9132b547dae7ba452c4d99a79e84a370 \
@@ -214,10 +222,18 @@ pyparsing==2.4.7 \
214222
--hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 \
215223
--hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b \
216224
# via packaging
225+
pytest-forked==1.1.3 \
226+
--hash=sha256:1805699ed9c9e60cb7a8179b8d4fa2b8898098e82d229b0825d8095f0f261100 \
227+
--hash=sha256:1ae25dba8ee2e56fb47311c9638f9e58552691da87e82d25b0ce0e4bf52b7d87 \
228+
# via pytest-xdist
229+
pytest-xdist==1.31.0 \
230+
--hash=sha256:0f46020d3d9619e6d17a65b5b989c1ebbb58fc7b1da8fb126d70f4bac4dfeed1 \
231+
--hash=sha256:7dc0d027d258cd0defc618fb97055fbd1002735ca7a6d17037018cf870e24011 \
232+
# via -r requirements.in
217233
pytest==5.4.1 \
218234
--hash=sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172 \
219235
--hash=sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970 \
220-
# via -r requirements.in
236+
# via -r requirements.in, pytest-forked, pytest-xdist
221237
python-dateutil==2.8.1 \
222238
--hash=sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c \
223239
--hash=sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a \
@@ -264,7 +280,7 @@ secretstorage==3.1.2 \
264280
six==1.14.0 \
265281
--hash=sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a \
266282
--hash=sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c \
267-
# via bleach, cryptography, packaging, python-dateutil, readme-renderer
283+
# via bleach, cryptography, packaging, pytest-xdist, python-dateutil, readme-renderer
268284
text-unidecode==1.3 \
269285
--hash=sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8 \
270286
--hash=sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93 \

requirements/requirements.in

+1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ multilint
1313
numpy
1414
pygments
1515
pytest
16+
pytest-xdist
1617
secretstorage # required for twine on linux
1718
twine

src/pytest_randomly.py

+26-9
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646

4747

4848
def seed_type(string):
49-
if string == "last":
49+
if string in ("default", "last"):
5050
return string
5151
try:
5252
return int(string)
@@ -62,7 +62,7 @@ def pytest_addoption(parser):
6262
"--randomly-seed",
6363
action="store",
6464
dest="randomly_seed",
65-
default=str(default_seed),
65+
default="default",
6666
type=seed_type,
6767
help="""Set the seed that pytest-randomly uses (int), or pass the
6868
special value 'last' to reuse the seed from the previous run.
@@ -87,6 +87,29 @@ def pytest_addoption(parser):
8787
)
8888

8989

90+
def pytest_configure(config):
91+
seed_value = config.getoption("randomly_seed")
92+
if seed_value == "last":
93+
seed = config.cache.get("randomly_seed", default_seed)
94+
elif seed_value == "default":
95+
if hasattr(config, "workerinput"):
96+
# pytest-xdist: use seed generated on master.
97+
seed = config.workerinput["randomly_seed"]
98+
else:
99+
seed = default_seed
100+
else:
101+
seed = seed_value
102+
config.cache.set("randomly_seed", seed)
103+
config.option.randomly_seed = seed
104+
105+
106+
def pytest_configure_node(node):
107+
"""
108+
pytest-xdist hook. Send the selected seed through to the nodes.
109+
"""
110+
node.workerinput["randomly_seed"] = node.config.getoption("randomly_seed")
111+
112+
90113
random_states = {}
91114
np_random_states = {}
92115

@@ -125,13 +148,7 @@ def _reseed(config, offset=0):
125148

126149

127150
def pytest_report_header(config):
128-
seed_value = config.getoption("randomly_seed")
129-
if seed_value == "last":
130-
seed = config.cache.get("randomly_seed", default_seed)
131-
else:
132-
seed = seed_value
133-
config.cache.set("randomly_seed", seed)
134-
config.option.randomly_seed = seed
151+
seed = config.getoption("randomly_seed")
135152
_reseed(config)
136153
return "Using --randomly-seed={}".format(seed)
137154

tests/test_pytest_randomly.py

+22
Original file line numberDiff line numberDiff line change
@@ -668,3 +668,25 @@ def fake_entry_points():
668668

669669
# Need to run in-process so that monkeypatching works
670670
testdir.runpytest("--randomly-seed=1")
671+
672+
673+
@pytest.mark.parametrize("n", list(range(5)))
674+
def test_xdist(n, ourtestdir):
675+
"""
676+
This test does not expose the original bug (non-shared default seeds) with
677+
a very high probability, hence multiple runs.
678+
"""
679+
ourtestdir.makepyfile(
680+
test_one="def test_a(): pass",
681+
test_two="def test_a(): pass",
682+
test_three="def test_a(): pass",
683+
test_four="def test_a(): pass",
684+
test_five="def test_a(): pass",
685+
test_six="def test_a(): pass",
686+
)
687+
688+
out = ourtestdir.runpytest("-n 6", "-v", "--dist=loadfile")
689+
out.assert_outcomes(passed=6)
690+
691+
# Can't make any assertion on the order, since output comes back from
692+
# workers non-deterministically

0 commit comments

Comments
 (0)