it-swarm.com.de

django, das Umgebungsvariablen in Tests festlegt

Ich möchte Umgebungsvariablen in meiner Django-App festlegen können, damit Tests ausgeführt werden können. Zum Beispiel basieren meine Ansichten auf mehreren API-Schlüsseln.

Es gibt Möglichkeiten, Einstellungen während des Tests zu überschreiben , aber ich möchte nicht, dass sie in settings.py definiert werden, da dies ein Sicherheitsrisiko ist. 

Ich habe in meiner Setup-Funktion versucht, diese Umgebungsvariablen festzulegen, aber das funktioniert nicht, um der Django-Anwendung die Werte zu geben.

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

Wenn ich lokal teste, habe ich einfach eine .env-Datei, mit der ich laufe 

foreman start -e .env web

die os.environ mit Werten versorgt. Aber in Djangos unittest.TestCase hat es keine Möglichkeit (das weiß ich), um das einzustellen. 

Wie kann ich das umgehen?

20
lollercoaster

Wie @schillingt in den Kommentaren feststellt, war EnvironmentVarGuard der richtige Weg. 

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

Dadurch werden Umgebungsvariablen für die Dauer der with-Anweisung des Kontextobjekts korrekt festgelegt. 

13
lollercoaster

test.support.EnvironmentVarGuard ist eine interne API, die von Version zu Version mit brechenden (rückwärts inkompatiblen) Änderungen geändert werden kann. Tatsächlich dient das gesamte test-Paket nur zur internen Verwendung. Auf der Dokumentationsseite des Testpakets wurde ausdrücklich angegeben, dass es sich um interne Tests von Kernbibliotheken und NICHT um eine öffentliche API handelt. (siehe Links unten)

Sie sollten patch.dict() in pythons Standard-Bibliothek unittest.mock verwenden. Es kann als Kontextmanager, Dekorateur oder Klassendekorateur verwendet werden. Siehe Beispielcode, der aus der offiziellen Python-Dokumentation kopiert wurde.

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: Für diejenigen, die die Dokumentation nicht gründlich lesen und möglicherweise die Notiz übersehen haben, lesen Sie die Hinweise zu test unter

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

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

23
Devy

Die Verwendung von EnvironmentVarGuard ist keine gute Lösung, da sie in einigen Umgebungen fehlschlägt und in anderen funktioniert. siehe Beispiel unten.

 Python3.6 environment on gitlab ci

Eine bessere Lösung ist das, was von erewok vorgeschlagen wurde und das die Verwendung des unittest.mock in Python3 erfordert.

Angenommen, Sie verwenden nur das Beste

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

Wenn Sie Ihre Umgebungsvariablen in die settings.py-Datei von Django laden, gehen Sie wie folgt vor: 

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

Sie könnten dies verwenden: 

from Django.test import TestCase, override_settings

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

Ich benutze py.test als meinen Testläufer, und Sie können eine pytest.ini-Datei erstellen, in der Sie eine bestimmte Einstellungsdatei angeben können, die beim Ausführen von Tests verwendet werden soll.

Hier finden Sie die Dokumentation dazu:

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

Ich empfehle py.test generell als Testläufer, da es verschiedene Arten von Testklassen und sogar einfache Funktionen unterstützt und es sehr einfach ist, Fixtures oder anderen Code einzurichten, der vor und nach den Tests ausgeführt wird.

0
erewok

Alte Frage, aber es kam bei einer Google-Suche auf und keine der vorhandenen Antworten ist geeignet. Wenn Sie pytest verwenden, können env vars mithilfe der Monkeypatching-Funktionalität von pytest festgelegt/wiederhergestellt werden.

0
Tom

Anfangs war meine Env-Variable PARTNER_CODE auf wow gesetzt.

Ich könnte die env-Variable folgendermaßen ändern:

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

Jetzt sagt meine Env-Variable PARTNER_CODEsos.

0
Sekhar