wkwk_soprano’s blog

wkwkのメモです

pytestで環境変数の一時的な設定をしたい

TL;DR

環境変数に関係するメソッドのテストで、一時的に環境変数を書き換えたい→mock.patchを使うことで実現できる

やりたいこと

異常系のテストとして、環境変数IDが設定されていないときはKeyErrorが発生することを確認するテストを設けたい

設定

ファイルの構成は以下の通り

my_dir/
  ├ src/ 
  │   └ my_code.py 
  └ test/
      └ test_my_code.py

環境変数を取得するメソッドが以下のように存在していたとする(my_code.py)

from dataclasses import dataclass
import os

@dataclass
class getEnvNames:
    def __init__(self):
        self.id = os.environ["ID"]
        self.name = os.environ["NAME"]

テストの方針

環境変数を一時的に書き換える場合はunittest.mockmock.patchを使う
使い方は以下の通り

from unittest.mock import patch

with patch.dict("os.environ", {"ID": "test"}):
    test_func()

まずは正常系のテスト

単純に置き換えるだけであれば以下のような感じでOK

from unittest.mock import patch
from my_code import getEnvNames

def test_getEnvNames_success():
    with patch.dict("os.environ", {"ID": "1", "NAME": "test"}):
        target_class = getEnvNames()

    assert target_class.id = "1"
    assert target_class.name = "test"

次に異常系のテスト

今回の主題である環境変数が設定されていなときのバージョン いまのところ調べた感じだとwith句の中で環境変数の削除をするしかなさそう ここで設定された環境変数は一時的に削除されるようで、with句を出たらもとに戻っている様子

import pytest
from unittest.mock import patch
from my_code import getEnvNames

def test_getEnvNames_failure():
    os.environ["ID"] = "2"
    os.environ["NAME"] = "sample"

    with patch.dict("os.environ", {"ID": "1", "NAME": "test"}):
        os.environ.pop("ID", default=None)
        with pytest.raises(KeyError):
            getEnvNames()

    assert os.environ["ID"] == "2"
    assert os.environ["NAME"] == "sample"