From fb9f277a99c32dbdde251a1df1ae5bc64c4c7de6 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 10 Jan 2020 00:50:12 +0100 Subject: [PATCH 1/3] Node._repr_failure_py: use abspath with changed cwd Fixes https://github.com/pytest-dev/pytest/issues/6428. --- src/_pytest/nodes.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 4a79bc86157..61c6bc90ab4 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -362,8 +362,7 @@ def _repr_failure_py( truncate_locals = True try: - os.getcwd() - abspath = False + abspath = os.getcwd() != str(self.config.invocation_dir) except OSError: abspath = True From b98aa195e0cc3f468316358bcd49e7dbc4d13483 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 16 May 2020 11:36:22 -0300 Subject: [PATCH 2/3] Add test and changelog for #6428 --- changelog/6428.bugfix.rst | 2 ++ testing/test_nodes.py | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 changelog/6428.bugfix.rst diff --git a/changelog/6428.bugfix.rst b/changelog/6428.bugfix.rst new file mode 100644 index 00000000000..581b2b7cece --- /dev/null +++ b/changelog/6428.bugfix.rst @@ -0,0 +1,2 @@ +Paths appearing in error messages are now correct in case the current working directory has +changed since the start of the session. diff --git a/testing/test_nodes.py b/testing/test_nodes.py index dbb3e2e8f64..5bd31b34261 100644 --- a/testing/test_nodes.py +++ b/testing/test_nodes.py @@ -58,3 +58,30 @@ class FakeSession: outside = py.path.local("/outside") assert nodes._check_initialpaths_for_relpath(FakeSession, outside) is None + + +def test_failure_with_changed_cwd(testdir): + """ + Test failure lines should use absolute paths if cwd has changed since + invocation, so the path is correct (#6428). + """ + p = testdir.makepyfile( + """ + import os + import pytest + + @pytest.fixture + def private_dir(): + out_dir = 'ddd' + os.mkdir(out_dir) + old_dir = os.getcwd() + os.chdir(out_dir) + yield out_dir + os.chdir(old_dir) + + def test_show_wrong_path(private_dir): + assert False + """ + ) + result = testdir.runpytest() + result.stdout.fnmatch_lines([str(p) + ":*: AssertionError", "*1 failed in *"]) From 757bded13592ca05d124215124b5808d9290e063 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 16 May 2020 12:00:23 -0300 Subject: [PATCH 3/3] Use Path() instead of str for path comparison On Windows specifically is common to have drives diverging just by casing ("C:" vs "c:"), depending on the cwd provided by the user. --- src/_pytest/nodes.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 61c6bc90ab4..7a8c28cd4fd 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -29,6 +29,7 @@ from _pytest.mark.structures import MarkDecorator from _pytest.mark.structures import NodeKeywords from _pytest.outcomes import fail +from _pytest.pathlib import Path from _pytest.store import Store if TYPE_CHECKING: @@ -361,8 +362,14 @@ def _repr_failure_py( else: truncate_locals = True + # excinfo.getrepr() formats paths relative to the CWD if `abspath` is False. + # It is possible for a fixture/test to change the CWD while this code runs, which + # would then result in the user seeing confusing paths in the failure message. + # To fix this, if the CWD changed, always display the full absolute path. + # It will be better to just always display paths relative to invocation_dir, but + # this requires a lot of plumbing (#6428). try: - abspath = os.getcwd() != str(self.config.invocation_dir) + abspath = Path(os.getcwd()) != Path(self.config.invocation_dir) except OSError: abspath = True