it-swarm.com.ru

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 со значениями. Но в unittest.TestCase у Django нет (как мне известно) способа установить это. 

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

20
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

13
lollercoaster

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

Вы должны использовать patch.dict() в стандартной библиотеке Python 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

23
Devy

Использование EnvironmentVarGuard не является хорошим решением, так как в некоторых средах происходит сбой и работает в других. см. пример ниже.

 Python3.6 environment on gitlab ci

Лучшее решение - это то, что было предложено erewok , которое требует использования unittest.mock в 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')

`` `

3
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):
1
Lucas03

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

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

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

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

0
erewok

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

0
Tom

Первоначально моя переменная env PARTNER_CODE была установлена ​​в wow.

Я мог бы изменить переменную env, используя следующее:

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

Теперь моя переменная env PARTNER_CODE говорит о sos.

0
Sekhar