diff --git a/changelog/7336.breaking.rst b/changelog/7336.breaking.rst new file mode 100644 index 00000000000..31d44f11cff --- /dev/null +++ b/changelog/7336.breaking.rst @@ -0,0 +1 @@ +The pytest ``--log-file`` cli or ``log_file`` ini marker is now relative to the configs ``inifile`` directory, as it was always the intention. It was originally introduced as relative to the current working directory unintentionally. diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index 796fa9b0ae0..68a96019e8a 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -161,11 +161,12 @@ def determine_setup( args: List[str], rootdir_cmd_arg: Optional[str] = None, config: Optional["Config"] = None, -) -> Tuple[py.path.local, Optional[str], Dict[str, Union[str, List[str]]]]: +) -> Tuple[py.path.local, Optional[py.path.local], Dict[str, Union[str, List[str]]]]: rootdir = None dirs = get_dirs_from_args(args) if inifile: - inicfg = load_config_dict_from_file(py.path.local(inifile)) or {} + inifile = py.path.local(inifile) + inicfg = load_config_dict_from_file(inifile) or {} if rootdir_cmd_arg is None: rootdir = get_common_ancestor(dirs) else: diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index ef90c94e862..7e666f6927a 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -527,6 +527,10 @@ def __init__(self, config: Config) -> None: # File logging. self.log_file_level = get_log_level_for_setting(config, "log_file_level") log_file = get_option_ini(config, "log_file") or os.devnull + + # Keep the log file relative to the inidir file (if it exists) (#7336) + if log_file != os.devnull and config.inifile is not None: + log_file = os.path.join(config.inifile.dirname, log_file) self.log_file_handler = _FileHandler(log_file, mode="w", encoding="UTF-8") log_file_format = get_option_ini(config, "log_file_format", "log_format") log_file_date_format = get_option_ini( diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index bbdf28b389a..b2871998353 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -1152,3 +1152,87 @@ def test_bad_log(monkeypatch): ) result = testdir.runpytest() result.assert_outcomes(passed=1) + + +def test_log_file_is_in_pytest_ini_rootdir(testdir, monkeypatch): + """ + #7336|#7350 - log_file should be relative to the config inifile + """ + testdir.makefile( + ".ini", + pytest=""" + [pytest] + log_cli = True + log_cli_level = DEBUG + log_file = logfile.txt + log_file_level = DEBUG + """, + ) + sub = testdir.mkdir("sub") + p = testdir.makepyfile( + """ + def test_this(): + import logging + logging.getLogger().info("Normal message") + """ + ) + p.move(sub.join(p.basename)) + monkeypatch.chdir(sub.strpath) + testdir.runpytest() + testdir.chdir() + files = set(os.listdir()) + assert {"logfile.txt", "pytest.ini"}.issubset(files) + + +def test_log_file_can_be_specified_to_child_dir(testdir, monkeypatch): + """ + #7336|#7350 - log_file should be relative to the config inifile + """ + testdir.makefile( + ".ini", + pytest=""" + [pytest] + log_cli = True + log_cli_level = DEBUG + log_file = sub/logfile.txt + log_file_level = DEBUG + """, + ) + sub = testdir.mkdir("sub") + p = testdir.makepyfile( + """ + def test_this(): + pass + """ + ) + p.move(sub.join(p.basename)) + monkeypatch.chdir(sub.strpath) + testdir.runpytest() + files = set(os.listdir()) + assert "logfile.txt" in files + assert "pytest.ini" not in files + + +def test_log_file_cli_is_also_relative(testdir, monkeypatch): + """ + #7336|#7350 - log_file should be relative to the config inifile + """ + testdir.makefile( + ".ini", + pytest=""" + [pytest] + """, + ) + sub = testdir.mkdir("sub") + p = testdir.makepyfile( + """ + def test_this(): + pass + """ + ) + p.move(sub.join(p.basename)) + monkeypatch.chdir(sub.strpath) + testdir.runpytest("--log-file", "sub{}logfile.txt".format(os.sep)) + files = set(os.listdir()) + assert "logfile.txt" in files + assert "pytest.ini" not in files