Параметры переменных среды 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 у него нет способа (я знаю) установить это.

Как я могу обойти это?

Ответ 1

Как заметил в комментариях @schillingt, EnvironmentVarGuard был правильным.

from test.test_support import EnvironmentVarGuard
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

Это правильно устанавливает переменные среды для продолжительности выражения объекта context with.

Ответ 2

test.support.EnvironmentVarGuard - это внутренний API, который может быть изменен с версии на версию с нарушениями (обратно несовместимыми). Фактически, весь пакет test используется только для внутреннего использования. На странице документации тестового пакета явно указано, что он предназначен для внутренней проверки основных библиотек и НЕ открытого API. (см. ссылки ниже)

Вы должны использовать patch.dict() в стандартной версии python lib unittest.mock. Его можно использовать в качестве менеджера контекста, декоратора или декоратора. См. Пример кода ниже, скопированного из официальной документации 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

Ответ 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

Я использую py.test как мой тестовый бегун, и он позволяет вам создать файл pytest.ini, в котором вы можете указать конкретный файл настроек, который будет использоваться во время выполнения тестов.

См. документацию по этому вопросу:

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

Я рекомендую py.test вообще как тестовый бегун, потому что он поддерживает различные типы тестовых классов и даже простые функции, и довольно легко настроить приборы или другой код, который работает до и после тестов.

Ответ 5

Старый вопрос, но он появился в поиске Google, и ни один из существующих ответов не подходит. Если вы используете pytest, env vars можно установить/восстановить с помощью функции pytest monkeypatching.