django在单元测试中设置环境变量

时间:2022-05-06 22:45:54

I want to be able to set environment variables in my Django app for tests to be able to run. For instance, my views rely on several API keys.

我希望能够在我的Django应用程序中设置环境变量,以便能够运行测试。例如,我的观点依赖于几个API密钥。

There are ways to override settings during testing, but I don't want them defined in settings.py as that is a security issue.

有一些方法可以在测试期间覆盖设置,但我不希望它们在settings.py中定义,因为这是一个安全问题。

I've tried in my setup function to set these environment variables, but that doesn't work to give the Django application the values.

我已经尝试在我的设置函数中设置这些环境变量,但这不能为Django应用程序提供值。

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

When I test locally, I simply have an .env file I run with

当我在本地测试时,我只是运行了一个.env文件

foreman start -e .env web

which supplies os.environ with values. But in Django's unittest.TestCase it does not have a way (that I know) to set that.

它为os.environ提供了价值。但是在Django的unittest.TestCase中,它没有办法(我知道)来设置它。

How can I get around this?

我怎么能绕过这个?

7 个解决方案

#1


18  

The test.support.EnvironmentVarGuard is an internal API that might be changed from version to version with breaking (backward incompatible) changes. In fact, the entire test package is internal use only. It was explicitly stated on the test package documentation page that it's for internal testing of core libraries and NOT a public API. (see links below)

test.support.EnvironmentVarGuard是一个内部API,可能会随着版本的变化而发生更改(向后不兼容)。实际上,整个测试包仅供内部使用。在测试包文档页面上明确指出它是用于核心库的内部测试而不是公共API。 (见下面的链接)

You should use patch.dict() in python's standard lib unittest.mock. It can be used as a context manager, decorator or class decorator. See example code below copied from the official Python documentation.

你应该在python的标准lib 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

Update: for those who doesn't read the documentation thoroughly and might have missed the note, read more test package notes at

更新:对于那些没有彻底阅读文档但可能错过了注释的人,请阅读更多测试包说明

https://docs.python.org/2/library/test.html or

https://docs.python.org/2/library/test.html或

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

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

#2


11  

As @schillingt noted in the comments, EnvironmentVarGuard was the correct way.

正如@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

This correctly sets environment variables for the duration of the context object with statement.

这会使用statement正确设置上下文对象持续时间的环境变量。

#3


1  

If you are loading your environment variables in Django's settings.py file like this:
import os ENV_NAME = os.environ.get('ENV_NAME', 'default')
You could use this:
from django.test import TestCase, override_settings @override_settings(ENV_NAME="super_setting") def test_...(self):

如果你在Django的settings.py文件中加载环境变量,如下所示:import os ENV_NAME = os.environ.get('ENV_NAME','default')你可以使用这个:来自django.test import TestCase,override_settings @override_settings( ENV_NAME =“super_setting”)def test _...(self):

#4


1  

Using EnvironmentVarGuard is not a good solution as it fails in some environments and works in others. see example below.

使用EnvironmentVarGuard不是一个好的解决方案,因为它在某些环境中失败并在其他环境中工作。见下面的例子。

django在单元测试中设置环境变量

A better solution is what was suggested by erewok that requires making use of the unittest.mock in python3.

更好的解决方案是erewok建议的,它需要在python3中使用unittest.mock。

Assuming using unittest

假设使用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


0  

I use py.test as my test runner, and it allows you to create a pytest.ini file in which you can specify a particular settings file to use while running tests.

我使用py.test作为我的测试运行器,它允许您创建一个pytest.ini文件,您可以在其中指定运行测试时要使用的特定设置文件。

See documentation on this here:

请参阅此处的文档:

http://pytest-django.readthedocs.org/en/latest/configuring_django.html#pytest-ini-settings

http://pytest-django.readthedocs.org/en/latest/configuring_django.html#pytest-ini-settings

I recommend py.test in general as a test runner, because it supports different types of test classes and even simple functions, and it's pretty easy to set up fixtures or other code that runs before and after tests.

我建议将py.test作为测试运行器,因为它支持不同类型的测试类甚至简单的函数,并且设置在测试之前和之后运行的灯具或其他代码非常容易。

#6


0  

Old question, but it turned up in a Google search and neither of the existing answers are suitable. If you're using pytest, env vars can be set/restored using pytest's monkeypatching functionality.

旧的问题,但它出现在谷歌搜索中,现有的答案都不合适。如果你正在使用pytest,可以使用pytest的monkeypatching功能设置/恢复env vars。

#7


0  

Initially, my env variable PARTNER_CODE was set to wow.

最初,我的env变量PARTNER_CODE设置为哇。

I could able to change the env variable using the following:

我可以使用以下内容更改env变量:

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

Now my env variable PARTNER_CODE says sos.

现在我的env变量PARTNER_CODE说sos。

#1


18  

The test.support.EnvironmentVarGuard is an internal API that might be changed from version to version with breaking (backward incompatible) changes. In fact, the entire test package is internal use only. It was explicitly stated on the test package documentation page that it's for internal testing of core libraries and NOT a public API. (see links below)

test.support.EnvironmentVarGuard是一个内部API,可能会随着版本的变化而发生更改(向后不兼容)。实际上,整个测试包仅供内部使用。在测试包文档页面上明确指出它是用于核心库的内部测试而不是公共API。 (见下面的链接)

You should use patch.dict() in python's standard lib unittest.mock. It can be used as a context manager, decorator or class decorator. See example code below copied from the official Python documentation.

你应该在python的标准lib 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

Update: for those who doesn't read the documentation thoroughly and might have missed the note, read more test package notes at

更新:对于那些没有彻底阅读文档但可能错过了注释的人,请阅读更多测试包说明

https://docs.python.org/2/library/test.html or

https://docs.python.org/2/library/test.html或

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

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

#2


11  

As @schillingt noted in the comments, EnvironmentVarGuard was the correct way.

正如@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

This correctly sets environment variables for the duration of the context object with statement.

这会使用statement正确设置上下文对象持续时间的环境变量。

#3


1  

If you are loading your environment variables in Django's settings.py file like this:
import os ENV_NAME = os.environ.get('ENV_NAME', 'default')
You could use this:
from django.test import TestCase, override_settings @override_settings(ENV_NAME="super_setting") def test_...(self):

如果你在Django的settings.py文件中加载环境变量,如下所示:import os ENV_NAME = os.environ.get('ENV_NAME','default')你可以使用这个:来自django.test import TestCase,override_settings @override_settings( ENV_NAME =“super_setting”)def test _...(self):

#4


1  

Using EnvironmentVarGuard is not a good solution as it fails in some environments and works in others. see example below.

使用EnvironmentVarGuard不是一个好的解决方案,因为它在某些环境中失败并在其他环境中工作。见下面的例子。

django在单元测试中设置环境变量

A better solution is what was suggested by erewok that requires making use of the unittest.mock in python3.

更好的解决方案是erewok建议的,它需要在python3中使用unittest.mock。

Assuming using unittest

假设使用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


0  

I use py.test as my test runner, and it allows you to create a pytest.ini file in which you can specify a particular settings file to use while running tests.

我使用py.test作为我的测试运行器,它允许您创建一个pytest.ini文件,您可以在其中指定运行测试时要使用的特定设置文件。

See documentation on this here:

请参阅此处的文档:

http://pytest-django.readthedocs.org/en/latest/configuring_django.html#pytest-ini-settings

http://pytest-django.readthedocs.org/en/latest/configuring_django.html#pytest-ini-settings

I recommend py.test in general as a test runner, because it supports different types of test classes and even simple functions, and it's pretty easy to set up fixtures or other code that runs before and after tests.

我建议将py.test作为测试运行器,因为它支持不同类型的测试类甚至简单的函数,并且设置在测试之前和之后运行的灯具或其他代码非常容易。

#6


0  

Old question, but it turned up in a Google search and neither of the existing answers are suitable. If you're using pytest, env vars can be set/restored using pytest's monkeypatching functionality.

旧的问题,但它出现在谷歌搜索中,现有的答案都不合适。如果你正在使用pytest,可以使用pytest的monkeypatching功能设置/恢复env vars。

#7


0  

Initially, my env variable PARTNER_CODE was set to wow.

最初,我的env变量PARTNER_CODE设置为哇。

I could able to change the env variable using the following:

我可以使用以下内容更改env变量:

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

Now my env variable PARTNER_CODE says sos.

现在我的env变量PARTNER_CODE说sos。