web-dev-qa-db-ja.com

django unittestテストで環境変数を設定する

Djangoアプリで環境変数を設定して、テストを実行できるようにしたい。たとえば、私のビューはいくつかのAPIキーに依存している。

テスト中に設定をオーバーライドする の方法がありますが、settings.pyで定義することはセキュリティ上の問題であるため、望ましくありません。

私はセットアップ関数でこれらの環境変数を設定しようとしましたが、Djangoアプリケーションに値を与えるためには機能しません。

class MyTests(TestCase):
    def setUp(self):
        os.environ['TEST'] = '123'  # doesn't propogate to app

ローカルでテストするとき、実行する.envファイルがあるだけです

foreman start -e .env web

os.environに値を提供します。しかし、Djangoのunittest.TestCaseには、それを設定する方法(私が知っていること)がありません。

どうすればこれを回避できますか?

25
lollercoaster

コメントで@schillingtが指摘したように、 EnvironmentVarGuard が正しい方法でした。

from test.test_support import EnvironmentVarGuard # Python(2.7 < 3)
from test.support import EnvironmentVarGuard # Python >=3
from Django.test import TestCase

class MyTestCase(TestCase):
    def setUp(self):
        self.env = EnvironmentVarGuard()
        self.env.set('VAR', 'value')

    def test_something(self):
        with self.env:
            # ... perform tests here ... #
            pass

これにより、コンテキストオブジェクトwithステートメントの実行中に環境変数が正しく設定されます。

14
lollercoaster

_test.support.EnvironmentVarGuard_は内部APIであり、バージョンごとに重大な(後方互換性のない)変更が加えられる可能性があります。 実際、testパッケージ全体は内部使用のみです。テストパッケージのドキュメントページで、コアライブラリの内部テスト用であり、パブリックAPI。 (以下のリンクを参照)

Pythonの標準ライブラリ_unittest.mock_で patch.dict() を使用する必要があります。コンテキストマネージャ、デコレータ、またはクラスデコレータとして使用できます。公式のPythonドキュメントからコピーした以下のコード例を参照してください。

_import os
from unittest.mock import patch
with patch.dict('os.environ', {'newkey': 'newvalue'}):
    print(os.environ['newkey'])  # should print out 'newvalue'
    assert 'newkey' in os.environ  # should be True
assert 'newkey' not in os.environ  # should be True
_

更新:ドキュメントを完全に読んでおらず、メモを見逃している可能性がある人は、次のtestパッケージノートを読んでください。

https://docs.python.org/2/library/test.html または

https://docs.python.org/3/library/test.html

32
Devy

EnvironmentVarGuardの使用は、一部の環境では失敗し、他の環境では機能するため、適切なソリューションではありません。以下の例を参照してください。

Python3.6 environment on gitlab ci

より良い解決策は、 erewok によって提案されたもので、unittest.mock in python3。

Unittestを使用すると仮定する

from unittest.mock import patch
class TestCase(unittest.TestCase):

    def setUp(self):
        self.env = patch.dict('os.environ', {'hello':'world'})

    def test_scenario_1(self):
        with self.env:
            self.assertEqual(os.environ.get('hello'), 'world')

`` `

5
gbozee

次のようにDjangoのsettings.pyファイルに環境変数を読み込んでいる場合:

import os
ENV_NAME = os.environ.get('ENV_NAME', 'default')

これを使用できます:

from Django.test import TestCase, override_settings

@override_settings(ENV_NAME="super_setting")
def test_...(self):
3
Lucas03

私が使う py.testをテストランナーとして使用すると、pytest.iniファイルでは、テストの実行中に使用する特定の設定ファイルを指定できます。

こちらのドキュメントをご覧ください:

http://pytest-Django.readthedocs.org/en/latest/configuring_Django.html#pytest-ini-settings

Py.testは一般にテストランナーとしてお勧めします。さまざまな種類のテストクラスや単純な関数もサポートし、テストの前後に実行されるフィクスチャやその他のコードを設定するのは非常に簡単だからです。

1
erewok

古い質問ですが、Google検索で見つかったため、既存の回答はいずれも適切ではありません。 pytestを使用している場合、env変数は pytestのモンキーパッチ機能 を使用して設定/復元できます。

0
Tom

最初は、私のenv変数PARTNER_CODEwowに設定されました。

次を使用してenv変数を変更できました。

from test.support import EnvironmentVarGuard
with EnvironmentVarGuard() as env:
   env['PARTNER_CODE'] = 'sos'

今私の環境変数PARTNER_CODEsosと言います。

0
Sekhar