Skip to content

xdist continues test execution in the background with '--exitfirst' #420

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
yadutaf opened this issue Mar 1, 2019 · 0 comments
Open

Comments

@yadutaf
Copy link

yadutaf commented Mar 1, 2019

When running pytest with --exitfirst or --maxfail=<some non zero value>, the main pytest session exits on the first failure as expected. However, the test workers are still executing the tests in the background.

The --exitfirst flag is very powerful when investigating test failures in scenarios where the tests have side-effects and starting the next test may destroy valuable execution traces 😃

Here is a minimal test suite to reproduce the issue:

import os
import unittest

logfile = open('/tmp/pytest.log', 'a')
worker = os.environ.get('PYTEST_XDIST_WORKER', 'single')

def log(line):
    logfile.write("[%s] %s\n" % (worker, line))

class TestPytest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        log("setUpClass")

    def setUp(self):
        log("setUp")

    def test_1(self):
        log("test_1")

    def test_2(self):
        log("test_2")
        assert False

    def test_3(self):
        log("test_3")

Test run with xdist:

rm -f /tmp/pytest.log && pytest-3 -x -d --tx popen//python=python3 test_pytest.py; cat /tmp/pytest.log
(actual test output redacted)
[gw0] setUpClass
[gw0] setUp
[gw0] test_1
[gw0] setUp
[gw0] test_2
[gw0] setUp
[gw0] test_3

Test run without xdist:

rm -f /tmp/pytest.log && pytest-3 -x test_pytest.py; cat /tmp/pytest.log
(actual test output redacted)
[single] setUpClass
[single] setUp
[single] test_1
[single] setUp
[single] test_2

Here is a partial patch to address this issue:

diff --git a/xdist/remote.py b/xdist/remote.py
index 346d6e5..36fc577 100644
--- a/xdist/remote.py
+++ b/xdist/remote.py
@@ -85,6 +85,8 @@ class WorkerInteractor:
         duration = time.time() - start
         self.sendevent("runtest_protocol_complete", item_index=self.item_index,
                        duration=duration)
+        if self.session.shouldfail:
+            raise self.session.Failed(self.session.shouldfail)
 
     def pytest_collection_finish(self, session):
         self.sendevent(
@@ -106,6 +108,8 @@ class WorkerInteractor:
         data["worker_id"] = self.workerid
         assert self.session.items[self.item_index].nodeid == report.nodeid
         self.sendevent("testreport", data=data)
+        if report.failed and self.config.getvalue("maxfail"):
+            self.session.shouldfail = "Immediately exit worker on failure"
 
     def pytest_collectreport(self, report):
         data = serialize_report(report)

When maxfail is set, this patch causes the worker to exit on the first failure. This implements the behavior of --exitfirst in the worker. However, when using --maxfail=<some non zero/non one value>, this produces a stacktrace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants