Skip to content

Commit 407d6e1

Browse files
authored
Do not show internal error when running out of workers (#437)
Do not show internal error when running out of workers
2 parents e165c2f + 956c797 commit 407d6e1

File tree

4 files changed

+57
-20
lines changed

4 files changed

+57
-20
lines changed

changelog/435.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
No longer show an internal error when we run out of workers due to crashes.

changelog/435.feature.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
When the test session is interrupted due to running out of workers, the reason is shown in the test summary
2+
for easier viewing.

src/xdist/dsession.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ def __init__(self, config):
4747
self._active_nodes = set()
4848
self._failed_nodes_count = 0
4949
self._max_worker_restart = get_default_max_worker_restart(self.config)
50-
50+
# summary message to print at the end of the session
51+
self._summary_report = None
5152
try:
5253
self.terminal = config.pluginmanager.getplugin("terminalreporter")
5354
except KeyError:
@@ -197,15 +198,23 @@ def worker_errordown(self, node, error):
197198
)
198199
if maximum_reached:
199200
if self._max_worker_restart == 0:
200-
msg = "Worker restarting disabled"
201+
msg = "worker {} crashed and worker restarting disabled".format(
202+
node.gateway.id
203+
)
201204
else:
202-
msg = "Maximum crashed workers reached: %d" % self._max_worker_restart
203-
self.report_line(msg)
205+
msg = "maximum crashed workers reached: %d" % self._max_worker_restart
206+
self._summary_report = msg
207+
self.report_line("\n" + msg)
208+
self.triggershutdown()
204209
else:
205-
self.report_line("Replacing crashed worker %s" % node.gateway.id)
210+
self.report_line("\nreplacing crashed worker %s" % node.gateway.id)
206211
self._clone_node(node)
207212
self._active_nodes.remove(node)
208213

214+
def pytest_terminal_summary(self, terminalreporter):
215+
if self.config.option.verbose >= 0 and self._summary_report:
216+
terminalreporter.write_sep("=", "xdist: {}".format(self._summary_report))
217+
209218
def worker_collectionfinish(self, node, ids):
210219
"""worker has finished test collection.
211220
@@ -315,7 +324,7 @@ def handle_crashitem(self, nodeid, worker):
315324
# XXX count no of failures and retry N times
316325
runner = self.config.pluginmanager.getplugin("runner")
317326
fspath = nodeid.split("::")[0]
318-
msg = "Worker %r crashed while running %r" % (worker.gateway.id, nodeid)
327+
msg = "worker %r crashed while running %r" % (worker.gateway.id, nodeid)
319328
rep = runner.TestReport(
320329
nodeid, (fspath, None, fspath), (), "failed", msg, "???"
321330
)

testing/acceptance_test.py

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -849,8 +849,8 @@ def test_b(): pass
849849
res = testdir.runpytest(f, "-n1")
850850
res.stdout.fnmatch_lines(
851851
[
852-
"*Replacing crashed worker*",
853-
"*Worker*crashed while running*",
852+
"replacing crashed worker gw*",
853+
"worker*crashed while running*",
854854
"*1 failed*1 passed*",
855855
]
856856
)
@@ -868,8 +868,8 @@ def test_d(): pass
868868
res = testdir.runpytest(f, "-n2")
869869
res.stdout.fnmatch_lines(
870870
[
871-
"*Replacing crashed worker*",
872-
"*Worker*crashed while running*",
871+
"replacing crashed worker gw*",
872+
"worker*crashed while running*",
873873
"*1 failed*3 passed*",
874874
]
875875
)
@@ -885,8 +885,8 @@ def test_b(): pass
885885
res = testdir.runpytest(f, "--dist=each", "--tx=popen")
886886
res.stdout.fnmatch_lines(
887887
[
888-
"*Replacing crashed worker*",
889-
"*Worker*crashed while running*",
888+
"replacing crashed worker gw*",
889+
"worker*crashed while running*",
890890
"*1 failed*1 passed*",
891891
]
892892
)
@@ -922,14 +922,35 @@ def test_d(): pass
922922
res = testdir.runpytest(f, "-n4", "--max-worker-restart=1")
923923
res.stdout.fnmatch_lines(
924924
[
925-
"*Replacing crashed worker*",
926-
"*Maximum crashed workers reached: 1*",
927-
"*Worker*crashed while running*",
928-
"*Worker*crashed while running*",
925+
"replacing crashed worker*",
926+
"maximum crashed workers reached: 1*",
927+
"worker*crashed while running*",
928+
"worker*crashed while running*",
929929
"*2 failed*2 passed*",
930930
]
931931
)
932932

933+
def test_max_worker_restart_tests_queued(self, testdir):
934+
f = testdir.makepyfile(
935+
"""
936+
import os, pytest
937+
@pytest.mark.parametrize('i', range(10))
938+
def test(i): os._exit(1)
939+
"""
940+
)
941+
res = testdir.runpytest(f, "-n2", "--max-worker-restart=3")
942+
res.stdout.fnmatch_lines(
943+
[
944+
"replacing crashed worker*",
945+
"maximum crashed workers reached: 3*",
946+
"worker*crashed while running*",
947+
"worker*crashed while running*",
948+
"* xdist: maximum crashed workers reached: 3 *",
949+
"* 4 failed in *",
950+
]
951+
)
952+
assert "INTERNALERROR" not in res.stdout.str()
953+
933954
def test_max_worker_restart_die(self, testdir):
934955
f = testdir.makepyfile(
935956
"""
@@ -939,7 +960,10 @@ def test_max_worker_restart_die(self, testdir):
939960
)
940961
res = testdir.runpytest(f, "-n4", "--max-worker-restart=0")
941962
res.stdout.fnmatch_lines(
942-
["*Unexpectedly no active workers*", "*INTERNALERROR*"]
963+
[
964+
"* xdist: worker gw* crashed and worker restarting disabled *",
965+
"* no tests ran in *",
966+
]
943967
)
944968

945969
def test_disable_restart(self, testdir):
@@ -954,9 +978,10 @@ def test_c(): pass
954978
res = testdir.runpytest(f, "-n4", "--max-worker-restart=0")
955979
res.stdout.fnmatch_lines(
956980
[
957-
"*Worker restarting disabled*",
958-
"*Worker*crashed while running*",
959-
"*1 failed*2 passed*",
981+
"worker gw* crashed and worker restarting disabled",
982+
"*worker*crashed while running*",
983+
"* xdist: worker gw* crashed and worker restarting disabled *",
984+
"* 1 failed, 2 passed in *",
960985
]
961986
)
962987

0 commit comments

Comments
 (0)