我希望能够在我的Django应用程序中设置环境变量,以便能够运行测试。例如,我的观点依赖于几个API密钥。
有override settings during testing的方法,但我不希望在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
中,它没有办法(我知道)来设置它。
我怎样才能解决这个问题?
答案 0 :(得分:28)
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
软件包说明
答案 1 :(得分:14)
正如@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
语句的持续时间内正确设置环境变量。
答案 2 :(得分:4)
使用EnvironmentVarGuard
不是一个好的解决方案,因为它在某些环境中失败并在其他环境中有效。见下面的例子。
更好的解决方案是erewok建议的,需要在python3中使用unittest.mock
。
假设使用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')
```
答案 3 :(得分:3)
如果要在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):
答案 4 :(得分:1)
我使用py.test
作为我的测试运行器,它允许您创建一个pytest.ini
文件,您可以在其中指定运行测试时要使用的特定设置文件。
请参阅此处的文档:
http://pytest-django.readthedocs.org/en/latest/configuring_django.html#pytest-ini-settings
我建议将py.test作为测试运行器,因为它支持不同类型的测试类甚至简单的函数,并且设置在测试之前和之后运行的灯具或其他代码非常容易。
答案 5 :(得分:1)
本文说明了所有内容,以下代码段对我有用 How to Mock Environment Variables in Python’s unittest
import os
from unittest import TestCase, mock
class SettingsTests(TestCase):
@classmethod
def setUpClass(cls):
cls.env_patcher = mock.patch.dict(os.environ, {"FROBNICATION_COLOUR": "ROUGE"})
cls.env_patcher.start()
super().setUpClass()
@classmethod
def tearDownClass(cls):
super().tearDownClass()
cls.env_patcher.stop()
def setUp(self):
super().setUp()
self.assertEqual(os.environ["FROBNICATION_COLOUR"], "ROUGE")
def test_frobnication_colour(self):
self.assertEqual(os.environ["FROBNICATION_COLOUR"], "ROUGE")
答案 6 :(得分:0)
旧问题,但它出现在谷歌搜索中,现有的答案都不合适。如果你正在使用pytest,可以使用pytest's monkeypatching functionality设置/恢复env变种。
答案 7 :(得分:0)
最初,我的env变量PARTNER_CODE
设置为wow
。
我可以使用以下内容更改env变量:
from test.support import EnvironmentVarGuard
with EnvironmentVarGuard() as env:
env['PARTNER_CODE'] = 'sos'
现在我的env变量PARTNER_CODE
说sos
。
答案 8 :(得分:0)
全程说明Mock Environment Variables in Python’s unittest
https://adamj.eu/tech/2020/10/13/how-to-mock-environment-variables-with-pythons-unittest/