Skip to content
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

Fix: pytest >=8.1.0 displays no diff for AssertionError with `--impor… #12716

Merged
merged 1 commit into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ Ted Xiao
Terje Runde
Thomas Grainger
Thomas Hisch
Tianyu Dongfang
Tim Hoffmann
Tim Strazny
TJ Bruno
Expand Down
1 change: 1 addition & 0 deletions changelog/12659.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed the issue of not displaying assertion failure differences when using the parameter ``--import-mode=importlib`` in pytest>=8.1.
10 changes: 10 additions & 0 deletions src/_pytest/assertion/rewrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ def find_spec(

# Type ignored because mypy is confused about the `self` binding here.
spec = self._find_spec(name, path) # type: ignore

if spec is None and path is not None:
# With --import-mode=importlib, PathFinder cannot find spec without modifying `sys.path`,
# causing inability to assert rewriting (#12659).
# At this point, try using the file path to find the module spec.
for _path_str in path:
spec = importlib.util.spec_from_file_location(name, _path_str)
if spec is not None:
break

if (
# the import machinery could not find a file to import
spec is None
Expand Down
4 changes: 3 additions & 1 deletion src/_pytest/pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,9 @@ def _import_module_using_spec(
# Checking with sys.meta_path first in case one of its hooks can import this module,
# such as our own assertion-rewrite hook.
for meta_importer in sys.meta_path:
spec = meta_importer.find_spec(module_name, [str(module_location)])
spec = meta_importer.find_spec(
module_name, [str(module_location), str(module_path)]
)
if spec_matches_module_path(spec, module_path):
break
else:
Expand Down
36 changes: 36 additions & 0 deletions testing/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1372,6 +1372,42 @@ def test_resolve_pkg_root_and_module_name_ns_multiple_levels(
)
assert mod is mod2

def test_ns_multiple_levels_import_rewrite_assertions(
self,
tmp_path: Path,
monkeypatch: MonkeyPatch,
pytester: Pytester,
) -> None:
dongfangtianyu marked this conversation as resolved.
Show resolved Hide resolved
"""Check assert rewriting with `--import-mode=importlib` (#12659)."""
self.setup_directories(tmp_path, monkeypatch, pytester)
code = dedent("""
def test():
assert "four lights" == "five lights"
""")

# A case is in a subdirectory with an `__init__.py` file.
test_py = tmp_path / "src/dist2/com/company/calc/algo/test_demo.py"
test_py.write_text(code, encoding="UTF-8")

pkg_root, module_name = resolve_pkg_root_and_module_name(
test_py, consider_namespace_packages=True
)
assert (pkg_root, module_name) == (
tmp_path / "src/dist2",
"com.company.calc.algo.test_demo",
)

result = pytester.runpytest("--import-mode=importlib", test_py)

result.stdout.fnmatch_lines(
[
"E AssertionError: assert 'four lights' == 'five lights'",
"E *",
"E - five lights*",
"E + four lights",
]
)

@pytest.mark.parametrize("import_mode", ["prepend", "append", "importlib"])
def test_incorrect_namespace_package(
self,
Expand Down
Loading