Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation: add setenv/delenv examples to monkeypatch docs #5250

Merged
merged 4 commits into from
May 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ Endre Galaczi
Eric Hunsberger
Eric Siegerman
Erik M. Bray
Evan Kepner
Fabien Zarifian
Fabio Zadrozny
Feng Ma
Expand Down
1 change: 1 addition & 0 deletions changelog/5250.doc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Expand docs on use of ``setenv`` and ``delenv`` with ``monkeypatch``.
80 changes: 77 additions & 3 deletions doc/en/monkeypatch.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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::
Expand Down Expand Up @@ -81,6 +81,80 @@ so that any attempts within tests to create http requests will fail.
See issue `#3290 <https://github.com/pytest-dev/pytest/issues/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:

.. 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")

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:

.. 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)

with pytest.raises(EnvironmentError):
_ = get_os_user_lower()

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()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto




.. currentmodule:: _pytest.monkeypatch

API Reference
Expand Down