diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 95f1332..d657b43 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -36,6 +36,18 @@ class TestDistribution: "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(): diff --git a/xdist/dsession.py b/xdist/dsession.py index 0ec92e9..88f2725 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_paths = {} try: self.terminal = config.pluginmanager.getplugin("terminalreporter") except KeyError: @@ -285,8 +286,16 @@ class DSession: self._handlefailures(rep) def slave_collectreport(self, node, rep): - self.config.hook.pytest_collectreport(report=rep) - 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. + str_path = str(rep.fspath) + if str_path not in self._failed_collection_paths: + self._failed_collection_paths[str_path] = True + self.config.hook.pytest_collectreport(report=rep) + self._handlefailures(rep) def _handlefailures(self, rep): if rep.failed: