web-dev-qa-db-fra.com

définition des variables d'environnement Django dans les tests unittest

Je veux pouvoir définir des variables d'environnement dans mon application Django pour que des tests puissent être exécutés. Par exemple, mes vues reposent sur plusieurs clés d’API.

Il existe des moyens pour remplacer les paramètres pendant le test , mais je ne veux pas qu'ils soient définis dans settings.py car c'est un problème de sécurité. 

J'ai essayé dans ma fonction de configuration de définir ces variables d'environnement, mais cela ne fonctionne pas pour donner les valeurs à l'application Django.

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

Lorsque je teste localement, j’ai simplement un fichier .env avec lequel je lance 

foreman start -e .env web

qui fournit os.environ avec des valeurs. Mais dans le unittest.TestCase de Django, il n’a pas de moyen (que je sache) de le définir. 

Comment puis-je contourner cela?

20
lollercoaster

Comme @schillingt l'a noté dans les commentaires, EnvironmentVarGuard était le bon moyen. 

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

Cela définit correctement les variables d'environnement pour la durée de l'instruction with de l'objet de contexte. 

13
lollercoaster

test.support.EnvironmentVarGuard est une API interne qui peut être modifiée de version en version avec des modifications de rupture (incompatibles en amont). En fait, l'intégralité du package test est à usage interne uniquement. Il a été explicitement indiqué sur la page de documentation du package de test qu'il s'agissait d'un test interne des bibliothèques principales et NON d'une API publique. (voir les liens ci-dessous)

Vous devez utiliser patch.dict() dans la bibliothèque standard de python unittest.mock. Il peut être utilisé en tant que gestionnaire de contexte, décorateur ou décorateur de classe. Voir l'exemple de code ci-dessous, copié de la documentation officielle de 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

Mise à jour: pour ceux qui ne lisent pas la documentation à fond et qui ont peut-être manqué la note, lisez plus de notes sur le paquet test à

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

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

23
Devy

L'utilisation de EnvironmentVarGuard n'est pas une bonne solution car elle échoue dans certains environnements et fonctionne dans d'autres. voir exemple ci-dessous.

 Python3.6 environment on gitlab ci

Une meilleure solution est celle suggérée par erewok qui nécessite l’utilisation du unittest.mock en python3.

En supposant d'utiliser 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

Si vous chargez vos variables d'environnement dans le fichier settings.py de Django, procédez comme suit: 

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

Vous pouvez utiliser ceci: 

from Django.test import TestCase, override_settings

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

J'utilise py.test comme testeur, et cela vous permet de créer un fichier pytest.ini dans lequel vous pouvez spécifier un fichier de paramètres particulier à utiliser lors de l'exécution de tests.

Voir la documentation à ce sujet ici:

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

Je recommande généralement py.test en tant que lanceur de tests, car il prend en charge différents types de classes de test et même des fonctions simples, et il est assez facile de configurer des fixtures ou tout autre code s'exécutant avant et après les tests.

0
erewok

Ancienne question, mais elle est apparue dans une recherche Google et aucune des réponses existantes ne convient. Si vous utilisez pytest, env vars peut être défini/restauré à l’aide de la fonctionnalité monkeypatching de pytest .

0
Tom

Initialement, ma variable env PARTNER_CODE a été définie sur wow.

J'ai pu changer la variable env en utilisant les éléments suivants:

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

Maintenant, ma variable env PARTNER_CODE dit sos.

0
Sekhar