From f013a5e8c1d375f2a5187fa2570627b8b05c45de Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 24 May 2019 16:46:50 +0200 Subject: [PATCH 1/2] pytester: use temporary HOME with spawn Followup to https://github.com/pytest-dev/pytest/issues/4956. --- changelog/4956.feature.rst | 1 + src/_pytest/pytester.py | 8 +++++++- testing/test_pytester.py | 23 +++++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 changelog/4956.feature.rst diff --git a/changelog/4956.feature.rst b/changelog/4956.feature.rst new file mode 100644 index 000000000..ab8357cda --- /dev/null +++ b/changelog/4956.feature.rst @@ -0,0 +1 @@ +pytester's ``testdir.spawn`` uses ``tmpdir`` as HOME/USERPROFILE directory. diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 1360d8d2f..e76eaa075 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -1233,7 +1233,13 @@ class Testdir(object): if sys.platform.startswith("freebsd"): pytest.xfail("pexpect does not work reliably on freebsd") logfile = self.tmpdir.join("spawn.out").open("wb") - child = pexpect.spawn(cmd, logfile=logfile) + + # Do not load user config. + env = os.environ.copy() + env["HOME"] = str(self.tmpdir) + env["USERPROFILE"] = env["HOME"] + + child = pexpect.spawn(cmd, logfile=logfile, env=env) self.request.addfinalizer(logfile.close) child.timeout = expect_timeout return child diff --git a/testing/test_pytester.py b/testing/test_pytester.py index b76d413b7..4d3833ba0 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -559,3 +559,26 @@ def test_popen_default_stdin_stderr_and_stdin_None(testdir): assert stdout.splitlines() == [b"", b"stdout"] assert stderr.splitlines() == [b"stderr"] assert proc.returncode == 0 + + +def test_spawn_uses_tmphome(testdir): + import os + + tmphome = str(testdir.tmpdir) + + # Does use HOME only during run. + assert os.environ.get("HOME") != tmphome + + p1 = testdir.makepyfile( + """ + import os + + def test(): + assert os.environ["HOME"] == {tmphome!r} + """.format( + tmphome=tmphome + ) + ) + child = testdir.spawn_pytest(str(p1)) + out = child.read() + assert child.wait() == 0, out.decode("utf8") From ace3a02cd485d1024a07d93dc8d58708a882587e Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 24 May 2019 17:49:14 +0200 Subject: [PATCH 2/2] pytester: factor out testdir._env_run_update --- src/_pytest/pytester.py | 15 ++++++++------- testing/test_pytester.py | 3 +++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index e76eaa075..605451630 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -508,6 +508,10 @@ class Testdir(object): # Discard outer pytest options. mp.delenv("PYTEST_ADDOPTS", raising=False) + # Environment (updates) for inner runs. + tmphome = str(self.tmpdir) + self._env_run_update = {"HOME": tmphome, "USERPROFILE": tmphome} + def __repr__(self): return "" % (self.tmpdir,) @@ -804,8 +808,8 @@ class Testdir(object): try: # Do not load user config (during runs only). mp_run = MonkeyPatch() - mp_run.setenv("HOME", str(self.tmpdir)) - mp_run.setenv("USERPROFILE", str(self.tmpdir)) + for k, v in self._env_run_update.items(): + mp_run.setenv(k, v) finalizers.append(mp_run.undo) # When running pytest inline any plugins active in the main test @@ -1045,9 +1049,7 @@ class Testdir(object): env["PYTHONPATH"] = os.pathsep.join( filter(None, [os.getcwd(), env.get("PYTHONPATH", "")]) ) - # Do not load user config. - env["HOME"] = str(self.tmpdir) - env["USERPROFILE"] = env["HOME"] + env.update(self._env_run_update) kw["env"] = env if stdin is Testdir.CLOSE_STDIN: @@ -1236,8 +1238,7 @@ class Testdir(object): # Do not load user config. env = os.environ.copy() - env["HOME"] = str(self.tmpdir) - env["USERPROFILE"] = env["HOME"] + env.update(self._env_run_update) child = pexpect.spawn(cmd, logfile=logfile, env=env) self.request.addfinalizer(logfile.close) diff --git a/testing/test_pytester.py b/testing/test_pytester.py index 4d3833ba0..54d364ca1 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -569,12 +569,15 @@ def test_spawn_uses_tmphome(testdir): # Does use HOME only during run. assert os.environ.get("HOME") != tmphome + testdir._env_run_update["CUSTOMENV"] = "42" + p1 = testdir.makepyfile( """ import os def test(): assert os.environ["HOME"] == {tmphome!r} + assert os.environ["CUSTOMENV"] == "42" """.format( tmphome=tmphome )