From ecd072ea94546024683a71f5f00208e9b4f5d3e0 Mon Sep 17 00:00:00 2001 From: Evan Kepner Date: Sun, 12 May 2019 09:52:22 -0400 Subject: [PATCH] add env example to monkeypatch docs --- doc/en/monkeypatch.rst | 68 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/doc/en/monkeypatch.rst b/doc/en/monkeypatch.rst index 1a69c3a42..b6f80f8ef 100644 --- a/doc/en/monkeypatch.rst +++ b/doc/en/monkeypatch.rst @@ -16,7 +16,7 @@ and a discussion of its motivation. Simple example: monkeypatching functions ---------------------------------------------------- +---------------------------------------- If you want to pretend that ``os.expanduser`` returns a certain directory, you can use the :py:meth:`monkeypatch.setattr` method to @@ -38,8 +38,8 @@ Here our test function monkeypatches ``os.path.expanduser`` and then calls into a function that calls it. After the test function finishes the ``os.path.expanduser`` modification will be undone. -example: preventing "requests" from remote operations ------------------------------------------------------- +Global patch example: preventing "requests" from remote operations +------------------------------------------------------------------ If you want to prevent the "requests" library from performing http requests in all your tests, you can do:: @@ -81,6 +81,68 @@ so that any attempts within tests to create http requests will fail. See issue `#3290 `_ for details. +Monkeypatching environment variables +------------------------------------ + +If you are working with environment variables you often need to safely change the values +or delete them from the system for testing purposes. ``Monkeypatch`` provides a mechanism +to do this using the ``setenv`` and ``delenv`` method. Our example code to test:: + + # contents of our original code file e.g. code.py + import os + + def get_os_user_lower(): + """Simple retrieval function. + Returns lowercase USER or raises EnvironmentError.""" + username = os.getenv("USER") + + if username is None: + raise EnvironmentError("USER environment is not set.") + + return username.lower() + +There are two potential paths. First, the ``USER`` environment variable is set to a +value. Second, the ``USER`` environment variable does not exist. Using ``monkeypatch`` +both paths can be safely tested without impacting the running environment:: + + # contents of our test file e.g. test_code.py + import pytest + + def test_upper_to_lower(monkeypatch): + """Set the USER env var to assert the behavior.""" + monkeypatch.setenv("USER", "TestingUser") + assert get_os_user_lower() == "testinguser" + + def test_raise_exception(monkeypatch): + """Remove the USER env var and assert EnvironmentError is raised.""" + monkeypatch.delenv("USER", raising=False) + + with pytest.raises(EnvironmentError): + _ = get_os_user_lower() + +This behavior can be be moved into ``fixture`` structures and shared across tests:: + + import pytest + + @pytest.fixture + def mock_env_user(monkeypatch): + monkeypatch.setenv("USER", "TestingUser") + + @pytest.fixture + def mock_env_missing(monkeypatch): + monkeypatch.delenv("USER", raising=False) + + # Notice the tests reference the fixtures for mocks + def test_upper_to_lower(mock_env_user): + assert get_os_user_lower() == "testinguser" + + def test_raise_exception(mock_env_missing): + with pytest.raises(EnvironmentError): + _ = get_os_user_lower() + + + + .. currentmodule:: _pytest.monkeypatch API Reference