Skip to content

Commit bf379f4

Browse files
Fix assertion rewriting with importlib mode (#12716) (#12755)
Fixes #12659 (cherry picked from commit 9a444d1) Co-authored-by: dongfangtianyu <7629022+dongfangtianyu@users.noreply.github.com>
1 parent be9e36e commit bf379f4

File tree

5 files changed

+51
-1
lines changed

5 files changed

+51
-1
lines changed

AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ Ted Xiao
412412
Terje Runde
413413
Thomas Grainger
414414
Thomas Hisch
415+
Tianyu Dongfang
415416
Tim Hoffmann
416417
Tim Strazny
417418
TJ Bruno

changelog/12659.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed the issue of not displaying assertion failure differences when using the parameter ``--import-mode=importlib`` in pytest>=8.1.

src/_pytest/assertion/rewrite.py

+10
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,16 @@ def find_spec(
101101

102102
# Type ignored because mypy is confused about the `self` binding here.
103103
spec = self._find_spec(name, path) # type: ignore
104+
105+
if spec is None and path is not None:
106+
# With --import-mode=importlib, PathFinder cannot find spec without modifying `sys.path`,
107+
# causing inability to assert rewriting (#12659).
108+
# At this point, try using the file path to find the module spec.
109+
for _path_str in path:
110+
spec = importlib.util.spec_from_file_location(name, _path_str)
111+
if spec is not None:
112+
break
113+
104114
if (
105115
# the import machinery could not find a file to import
106116
spec is None

src/_pytest/pathlib.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,9 @@ def _import_module_using_spec(
621621
# Checking with sys.meta_path first in case one of its hooks can import this module,
622622
# such as our own assertion-rewrite hook.
623623
for meta_importer in sys.meta_path:
624-
spec = meta_importer.find_spec(module_name, [str(module_location)])
624+
spec = meta_importer.find_spec(
625+
module_name, [str(module_location), str(module_path)]
626+
)
625627
if spec_matches_module_path(spec, module_path):
626628
break
627629
else:

testing/test_pathlib.py

+36
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,42 @@ def test_resolve_pkg_root_and_module_name_ns_multiple_levels(
13721372
)
13731373
assert mod is mod2
13741374

1375+
def test_ns_multiple_levels_import_rewrite_assertions(
1376+
self,
1377+
tmp_path: Path,
1378+
monkeypatch: MonkeyPatch,
1379+
pytester: Pytester,
1380+
) -> None:
1381+
"""Check assert rewriting with `--import-mode=importlib` (#12659)."""
1382+
self.setup_directories(tmp_path, monkeypatch, pytester)
1383+
code = dedent("""
1384+
def test():
1385+
assert "four lights" == "five lights"
1386+
""")
1387+
1388+
# A case is in a subdirectory with an `__init__.py` file.
1389+
test_py = tmp_path / "src/dist2/com/company/calc/algo/test_demo.py"
1390+
test_py.write_text(code, encoding="UTF-8")
1391+
1392+
pkg_root, module_name = resolve_pkg_root_and_module_name(
1393+
test_py, consider_namespace_packages=True
1394+
)
1395+
assert (pkg_root, module_name) == (
1396+
tmp_path / "src/dist2",
1397+
"com.company.calc.algo.test_demo",
1398+
)
1399+
1400+
result = pytester.runpytest("--import-mode=importlib", test_py)
1401+
1402+
result.stdout.fnmatch_lines(
1403+
[
1404+
"E AssertionError: assert 'four lights' == 'five lights'",
1405+
"E *",
1406+
"E - five lights*",
1407+
"E + four lights",
1408+
]
1409+
)
1410+
13751411
@pytest.mark.parametrize("import_mode", ["prepend", "append", "importlib"])
13761412
def test_incorrect_namespace_package(
13771413
self,

0 commit comments

Comments
 (0)