Intro

If you are working with environment variables you need to set, change or delete the values from the system for testing purposes. So how can we test them?

Let’s assume that we have a function that gets a “secret” key from os environment:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# utilities.py
import os


def get_secret():
    """Simple retrieval function.
    Returns SECRET or raises OSError.
    """
    secret = os.getenv('SECRET', default=None)

    if secret is None:
        raise OSError("SECRET environment is not set.")

    return secret

One way for testing would be put an env var into config files of test like tox.ini or pytest.ini

# tox.ini
[testenv]
setenv = SECRET=top_secret

Another way would be using pytest-env plugin and adding it into pytest.ini:

# pytest.ini
[pytest]
env =
    HOME=~/tmp
    SECRET=top_secret

However these methods are not preferred since it violates isolating tests.

Monkeypatching environment variables

Recommended way comes from pytest itself: monkeypatch. pytest provides a mechanism which gives the setenv and delenv methods.

First we set SECRET env var and test it, then testing OSError when SECRET not set. Since as we know; we always should test both “normal” and “failure” cases:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# test_utilities.py
import pytest

from utilities import get_user


def test_get_user(monkeypatch):
    """Set the SECRET env var to assert the behavior."""
    monkeypatch.setenv("SECRET", "top_secret")

    assert get_user() == "top_secret"


def test_get_user_exception(monkeypatch):
    """Remove the SECRET env var and assert OSError is raised."""
    monkeypatch.delenv("SECRET", raising=False)

    with pytest.raises(OSError):
        _ = get_user()

You can also use fixture structures and share across them tests. For more info please go to: pytest:testing env vars.

All done!