From ecd072ea94546024683a71f5f00208e9b4f5d3e0 Mon Sep 17 00:00:00 2001 From: Evan Kepner Date: Sun, 12 May 2019 09:52:22 -0400 Subject: [PATCH 1/4] 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 From 6ca3e1e425dc247e7f8c3f422e31d26e3ca727aa Mon Sep 17 00:00:00 2001 From: Evan Kepner Date: Sun, 12 May 2019 10:04:24 -0400 Subject: [PATCH 2/4] add @EvanKepner to authors --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index a5bb34039..95f763a96 100644 --- a/AUTHORS +++ b/AUTHORS @@ -86,6 +86,7 @@ Endre Galaczi Eric Hunsberger Eric Siegerman Erik M. Bray +Evan Kepner Fabien Zarifian Fabio Zadrozny Feng Ma From 2ad36b14029cbb96351d22248038f9057b496469 Mon Sep 17 00:00:00 2001 From: Evan Kepner Date: Sun, 12 May 2019 10:08:46 -0400 Subject: [PATCH 3/4] add #5250 changelog entry --- changelog/5250.doc.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/5250.doc.rst diff --git a/changelog/5250.doc.rst b/changelog/5250.doc.rst new file mode 100644 index 000000000..1b4c564a0 --- /dev/null +++ b/changelog/5250.doc.rst @@ -0,0 +1 @@ +Expand docs on use of ``setenv`` and ``delenv`` with ``monkeypatch``. From e668aaf885f15eca3d466af5688db179cffda0e3 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 14 May 2019 18:59:27 -0300 Subject: [PATCH 4/4] Fix indentation and use code-block directives The code-block directives are required by our blacken-docs hook --- doc/en/monkeypatch.rst | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/doc/en/monkeypatch.rst b/doc/en/monkeypatch.rst index b6f80f8ef..b45ad07c1 100644 --- a/doc/en/monkeypatch.rst +++ b/doc/en/monkeypatch.rst @@ -86,33 +86,40 @@ 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:: +to do this using the ``setenv`` and ``delenv`` method. Our example code to test: + +.. code-block:: python # 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") + """Simple retrieval function. + Returns lowercase USER or raises EnvironmentError.""" + username = os.getenv("USER") - if username is None: - raise EnvironmentError("USER environment is not set.") + if username is None: + raise EnvironmentError("USER environment is not set.") - return username.lower() + 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:: +both paths can be safely tested without impacting the running environment: + +.. code-block:: python # 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) @@ -120,29 +127,34 @@ both paths can be safely tested without impacting the running environment:: with pytest.raises(EnvironmentError): _ = get_os_user_lower() -This behavior can be be moved into ``fixture`` structures and shared across tests:: +This behavior can be be moved into ``fixture`` structures and shared across tests: + +.. code-block:: python 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