diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index f38e772..34596ee 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -24,6 +24,30 @@ class TestDistribution: "*1 failed*", ]) + def test_n1_import_error(self, testdir): + p1 = testdir.makepyfile(""" + import __import_of_missing_module + def test_import(): + pass + """) + result = testdir.runpytest(p1, "-n1") + assert result.ret == 1 + result.stdout.fnmatch_lines([ + "E ImportError: No module named __import_of_missing_module", + ]) + + def test_n2_import_error(self, testdir): + """Check that we don't report the same import error multiple times + in distributed mode.""" + p1 = testdir.makepyfile(""" + import __import_of_missing_module + def test_import(): + pass + """) + result1 = testdir.runpytest(p1, "-n2") + result2 = testdir.runpytest(p1, "-n1") + assert len(result1.stdout.lines) == len(result2.stdout.lines) + def test_n1_skip(self, testdir): p1 = testdir.makepyfile(""" def test_skip(): @@ -36,6 +60,18 @@ class TestDistribution: "*1 skipped*", ]) + def test_manytests_to_one_import_error(self, testdir): + p1 = testdir.makepyfile(""" + import __import_of_missing_module + def test_import(): + pass + """) + result = testdir.runpytest(p1, '--tx=popen', '--tx=popen') + assert result.ret == 1 + result.stdout.fnmatch_lines([ + "E ImportError: No module named __import_of_missing_module", + ]) + def test_manytests_to_one_popen(self, testdir): p1 = testdir.makepyfile(""" import py diff --git a/xdist/dsession.py b/xdist/dsession.py index b7d9b04..6ffc80c 100644 --- a/xdist/dsession.py +++ b/xdist/dsession.py @@ -159,6 +159,7 @@ class DSession: self.countfailures = 0 self.maxfail = config.getvalue("maxfail") self.queue = queue.Queue() + self._failed_collection_errors = {} try: self.terminal = config.pluginmanager.getplugin("terminalreporter") except KeyError: @@ -285,9 +286,16 @@ class DSession: self._handlefailures(rep) def slave_collectreport(self, node, rep): - #self.report_line("collectreport %s: %s" %(rep.id, rep.status)) - #rep.node = node - self._handlefailures(rep) + if rep.failed: + self._failed_slave_collectreport(node, rep) + + def _failed_slave_collectreport(self, node, rep): + # Check we haven't already seen this report (from + # another slave). + if rep.longrepr not in self._failed_collection_errors: + self._failed_collection_errors[rep.longrepr] = True + self.config.hook.pytest_collectreport(report=rep) + self._handlefailures(rep) def _handlefailures(self, rep): if rep.failed: