Skip to content

Commit

Permalink
pytester: testdir: setup monkeypatch via pytest_runtest_call (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
blueyed committed Feb 8, 2020
1 parent 974be8e commit 04a8ebe
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 26 deletions.
50 changes: 36 additions & 14 deletions src/_pytest/pytester.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from io import StringIO
from typing import Callable
from typing import Dict
from typing import Generator
from typing import Iterable
from typing import List
from typing import Optional
Expand All @@ -39,6 +40,7 @@
from _pytest.nodes import Collector
from _pytest.nodes import Item
from _pytest.pathlib import Path
from _pytest.python import Function
from _pytest.python import Module
from _pytest.reports import TestReport
from _pytest.tmpdir import TempdirFactory
Expand Down Expand Up @@ -535,6 +537,39 @@ def try_rel(arg: Path) -> Path:
print("{}: {}\n{}in: {}".format(header, args_str, indent, cwd))


@pytest.hookimpl(hookwrapper=True, trylast=True)
def pytest_runtest_call(item: Function) -> Generator[None, None, None]:
"""Setup/activate testdir's monkeypatching only during test calls.
When it would be done via the instance/fixture directly it would also be
active during teardown (e.g. with the terminal plugin's reporting), where
it might mess with the column width etc.
"""
testdir = item.funcargs.get("testdir")
if not isinstance(testdir, Testdir):
yield
return

mp = testdir.monkeypatch
mp.setenv("PYTEST_DEBUG_TEMPROOT", str(testdir.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)
# Ensure no user config is used.
tmphome = str(testdir.tmpdir)
mp.setenv("HOME", tmphome)
mp.setenv("USERPROFILE", tmphome)
# Do not use colors for inner runs by default.
mp.setenv("PY_COLORS", "0")

mp.setattr("_pytest.terminal._cached_terminal_width", None)
try:
yield
finally:
mp.undo()


class Testdir:
"""Temporary test directory with tools to test/run pytest itself.
Expand Down Expand Up @@ -575,20 +610,7 @@ def __init__(self, request: FixtureRequest, tmpdir_factory: TempdirFactory) -> N
self.chdir()
self.request.addfinalizer(self.finalize)
self._method = self.request.config.getoption("--runpytest")

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)
# Ensure no user config is used.
tmphome = str(self.tmpdir)
mp.setenv("HOME", tmphome)
mp.setenv("USERPROFILE", tmphome)
# Do not use colors for inner runs by default.
mp.setenv("PY_COLORS", "0")
mp.setattr("_pytest.terminal._cached_terminal_width", 80)
self.monkeypatch = MonkeyPatch()

def __repr__(self):
return "<Testdir {!r}>".format(self.tmpdir)
Expand Down
60 changes: 48 additions & 12 deletions testing/test_pytester.py
Original file line number Diff line number Diff line change
Expand Up @@ -573,17 +573,36 @@ def test_no_matching_after_match() -> None:


def test_pytester_addopts_before_testdir(request, monkeypatch) -> None:
orig = os.environ.get("PYTEST_ADDOPTS", None)
monkeypatch.setenv("PYTEST_ADDOPTS", "--orig-unused")
# Requesting the fixture dynamically / instantiating Testdir does not
# change the env via its monkeypatch instance.
testdir = request.getfixturevalue("testdir")
assert "PYTEST_ADDOPTS" not in os.environ
assert os.environ["PYTEST_ADDOPTS"] == "--orig-unused"

assert testdir.monkeypatch is not monkeypatch
testdir.monkeypatch.setenv("PYTEST_ADDOPTS", "-p pytester")

p1 = testdir.makepyfile(
"""
import os
def test(testdir):
assert "PYTEST_ADDOPTS" not in os.environ
def test2():
assert os.environ.get("PYTEST_ADDOPTS") == "-p pytester"
"""
)
result = testdir.runpytest(str(p1))
assert result.ret == 0

# Finalizer undos always, although a context is used via
# pytest_runtest_call.
testdir.finalize()
assert os.environ.get("PYTEST_ADDOPTS") == "--orig-unused"
monkeypatch.undo()
assert os.environ.get("PYTEST_ADDOPTS") == orig


def test_testdir_terminal_width(request, monkeypatch):
def test_testdir_terminal_width(monkeypatch):
"""testdir does not set COLUMNS, but _cached_terminal_width."""
from _pytest.terminal import get_terminal_width

Expand All @@ -595,18 +614,35 @@ def test_testdir_terminal_width(request, monkeypatch):
assert get_terminal_width() == 1234
monkeypatch.delenv("COLUMNS")

testdir = request.getfixturevalue("testdir")
assert get_terminal_width() == 80
assert "COLUMNS" not in os.environ
testdir.finalize()
assert get_terminal_width() == 1234
assert "COLUMNS" not in os.environ

monkeypatch.undo()
assert os.environ.get("COLUMNS") == orig_env
assert get_terminal_width() == orig_width


def test_testdir_terminal_width_inner(testdir, monkeypatch):
monkeypatch.setattr("_pytest.terminal._cached_terminal_width", 1234)
monkeypatch.delenv("COLUMNS", raising=False)

p1 = testdir.makepyfile(
"""
import os
from _pytest.terminal import get_terminal_width
def test1():
assert get_terminal_width() == 1234
def test2(testdir):
assert get_terminal_width() == 80
assert "COLUMNS" not in os.environ
testdir.finalize()
assert get_terminal_width() == 1234
assert "COLUMNS" not in os.environ
"""
)
result = testdir.runpytest("-p", "pytester", str(p1))
assert result.ret == 0


def test_run_stdin(testdir) -> None:
with pytest.raises(testdir.TimeoutExpired):
testdir.run(
Expand Down

0 comments on commit 04a8ebe

Please sign in to comment.