From 21ca38b932acc703c4fdd31364ab37ebc07a8cb1 Mon Sep 17 00:00:00 2001
From: Anthony Sottile <asottile@umich.edu>
Date: Wed, 27 May 2020 13:49:43 -0700
Subject: [PATCH] Merge pull request #7257 from DahlitzFlorian/fix-issue-6956

Prevent pytest from printing ConftestImportFailure traceback

(cherry picked from commit b3db440d4c41c91dd761dee98d7014149e1d7c08)
---
 changelog/6956.bugfix.rst | 1 +
 src/_pytest/nodes.py      | 6 ++++--
 testing/python/collect.py | 9 +++------
 testing/test_reports.py   | 8 ++++++++
 4 files changed, 16 insertions(+), 8 deletions(-)
 create mode 100644 changelog/6956.bugfix.rst

diff --git a/changelog/6956.bugfix.rst b/changelog/6956.bugfix.rst
new file mode 100644
index 00000000000..a88ef94b6d5
--- /dev/null
+++ b/changelog/6956.bugfix.rst
@@ -0,0 +1 @@
+Prevent pytest from printing ConftestImportFailure traceback to stdout.
diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py
index 7e6720d6026..7edea1e976c 100644
--- a/src/_pytest/nodes.py
+++ b/src/_pytest/nodes.py
@@ -19,6 +19,7 @@
 from _pytest.compat import cached_property
 from _pytest.compat import TYPE_CHECKING
 from _pytest.config import Config
+from _pytest.config import ConftestImportFailure
 from _pytest.config import PytestPluginManager
 from _pytest.deprecated import NODE_USE_FROM_PARENT
 from _pytest.fixtures import FixtureDef
@@ -28,7 +29,6 @@
 from _pytest.mark.structures import MarkDecorator
 from _pytest.mark.structures import NodeKeywords
 from _pytest.outcomes import fail
-from _pytest.outcomes import Failed
 from _pytest.store import Store
 
 if TYPE_CHECKING:
@@ -318,8 +318,10 @@ def _prunetraceback(self, excinfo):
         pass
 
     def _repr_failure_py(
-        self, excinfo: ExceptionInfo[Union[Failed, FixtureLookupError]], style=None
+        self, excinfo: ExceptionInfo[BaseException], style=None,
     ) -> Union[str, ReprExceptionInfo, ExceptionChainRepr, FixtureLookupErrorRepr]:
+        if isinstance(excinfo.value, ConftestImportFailure):
+            excinfo = ExceptionInfo(excinfo.value.excinfo)
         if isinstance(excinfo.value, fail.Exception):
             if not excinfo.value.pytrace:
                 return str(excinfo.value)
diff --git a/testing/python/collect.py b/testing/python/collect.py
index 496a22b0504..f493477c130 100644
--- a/testing/python/collect.py
+++ b/testing/python/collect.py
@@ -1225,7 +1225,7 @@ def test_syntax_error_with_non_ascii_chars(testdir):
     result.stdout.fnmatch_lines(["*ERROR collecting*", "*SyntaxError*", "*1 error in*"])
 
 
-def test_collecterror_with_fulltrace(testdir):
+def test_collect_error_with_fulltrace(testdir):
     testdir.makepyfile("assert 0")
     result = testdir.runpytest("--fulltrace")
     result.stdout.fnmatch_lines(
@@ -1233,15 +1233,12 @@ def test_collecterror_with_fulltrace(testdir):
             "collected 0 items / 1 error",
             "",
             "*= ERRORS =*",
-            "*_ ERROR collecting test_collecterror_with_fulltrace.py _*",
-            "",
-            "*/_pytest/python.py:*: ",
-            "_ _ _ _ _ _ _ _ *",
+            "*_ ERROR collecting test_collect_error_with_fulltrace.py _*",
             "",
             ">   assert 0",
             "E   assert 0",
             "",
-            "test_collecterror_with_fulltrace.py:1: AssertionError",
+            "test_collect_error_with_fulltrace.py:1: AssertionError",
             "*! Interrupted: 1 error during collection !*",
         ]
     )
diff --git a/testing/test_reports.py b/testing/test_reports.py
index 8c509ec479d..ef87af05883 100644
--- a/testing/test_reports.py
+++ b/testing/test_reports.py
@@ -395,6 +395,14 @@ def check_longrepr(longrepr):
         # for same reasons as previous test, ensure we don't blow up here
         loaded_report.longrepr.toterminal(tw_mock)
 
+    def test_report_prevent_ConftestImportFailure_hiding_exception(self, testdir):
+        sub_dir = testdir.tmpdir.join("ns").ensure_dir()
+        sub_dir.join("conftest").new(ext=".py").write("import unknown")
+
+        result = testdir.runpytest_subprocess(".")
+        result.stdout.fnmatch_lines(["E   *Error: No module named 'unknown'"])
+        result.stdout.no_fnmatch_line("ERROR  - *ConftestImportFailure*")
+
 
 class TestHooks:
     """Test that the hooks are working correctly for plugins"""
