diff --git a/changelog/5031.bugfix.rst b/changelog/5031.bugfix.rst new file mode 100644 index 000000000..6ad80b1e3 --- /dev/null +++ b/changelog/5031.bugfix.rst @@ -0,0 +1 @@ +Environment variables are properly restored when using pytester's ``testdir`` fixture. diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 7fc5eaf64..a802a56f0 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -476,9 +476,6 @@ class Testdir(object): name = request.function.__name__ self.tmpdir = tmpdir_factory.mktemp(name, numbered=True) self.test_tmproot = tmpdir_factory.mktemp("tmp-" + name, numbered=True) - os.environ["PYTEST_DEBUG_TEMPROOT"] = str(self.test_tmproot) - os.environ.pop("TOX_ENV_DIR", None) # Ensure that it is not used for caching. - os.environ.pop("PYTEST_ADDOPTS", None) # Do not use outer options. self.plugins = [] self._cwd_snapshot = CwdSnapshot() self._sys_path_snapshot = SysPathsSnapshot() @@ -491,6 +488,13 @@ class Testdir(object): elif method == "subprocess": self._runpytest_method = self.runpytest_subprocess + mp = self.monkeypatch = MonkeyPatch() + mp.setenv("PYTEST_DEBUG_TEMPROOT", str(self.test_tmproot)) + # Ensure no unexpected caching via tox. + mp.delenv("TOX_ENV_DIR", raising=False) + # Discard outer pytest options. + mp.delenv("PYTEST_ADDOPTS", raising=False) + def __repr__(self): return "" % (self.tmpdir,) @@ -508,7 +512,7 @@ class Testdir(object): self._sys_modules_snapshot.restore() self._sys_path_snapshot.restore() self._cwd_snapshot.restore() - os.environ.pop("PYTEST_DEBUG_TEMPROOT", None) + self.monkeypatch.undo() def __take_sys_modules_snapshot(self): # some zope modules used by twisted-related tests keep internal state @@ -799,11 +803,11 @@ class Testdir(object): """ finalizers = [] try: - # Do not load user config. - monkeypatch = MonkeyPatch() - monkeypatch.setenv("HOME", str(self.tmpdir)) - monkeypatch.setenv("USERPROFILE", str(self.tmpdir)) - finalizers.append(monkeypatch.undo) + # 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)) + finalizers.append(mp_run.undo) # When running pytest inline any plugins active in the main test # process are already imported. So this disables the warning which diff --git a/testing/test_pytester.py b/testing/test_pytester.py index 08167ec90..2e4877463 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -469,3 +469,16 @@ def test_linematcher_with_nonlist(): assert lm._getlines({}) == {} assert lm._getlines(set()) == set() + + +def test_pytester_addopts(request, monkeypatch): + monkeypatch.setenv("PYTEST_ADDOPTS", "--orig-unused") + + testdir = request.getfixturevalue("testdir") + + try: + assert "PYTEST_ADDOPTS" not in os.environ + finally: + testdir.finalize() + + assert os.environ["PYTEST_ADDOPTS"] == "--orig-unused"