2015-07-02 12 views
10

Ich möchte in meiner Django-App Umgebungsvariablen für Tests setzen können, um ausgeführt werden zu können. Zum Beispiel sind meine Ansichten auf mehrere API-Schlüssel angewiesen.django Einstellung Umgebungsvariablen in Unittest Tests

Es gibt Möglichkeiten zu override settings during testing, aber ich möchte nicht, dass sie in settings.py als ein Sicherheitsproblem definiert sind.

Ich habe in meiner Setup-Funktion versucht, diese Umgebungsvariablen zu setzen, 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 

Als ich vor Ort testen, habe ich einfach eine .env Datei, die ich mit

foreman start -e .env web 

laufen die os.environ mit Werten versorgt. Aber in Djangos unittest.TestCase hat es keinen Weg (den ich kenne), das zu setzen.

Wie kann ich das umgehen?

+2

Haben Sie versucht, mit [EnvironmentVarGuard] (https://docs.python.org/2/library/test.html#test.test_support.EnvironmentVarGuard)? – schillingt

+0

Ja, das war die richtige Antwort! – lollercoaster

Antwort

7

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

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 

Dies setzt die richtigen Umgebungsvariablen für die Dauer der Kontextobjekt with Aussage.

+1

Führt zu einem Importfehler. Darüber hinaus heißt es in der Dokumentation zu EnvironmentVarGuard: "Warnung Das Testpaket ist nur für den internen Gebrauch von Python gedacht. Es ist für die Kernentwickler von Python dokumentiert. Jede Verwendung dieses Pakets außerhalb der Python-Standardbibliothek wird vom erwähnten Code abgeraten hier kann sich die Version von Python ohne Ankündigung ändern oder entfernen. " – Nate

+3

Python 3 verschoben es zu 'von test.support Import EnvironmentVarGuard'. Wenn Sie jedoch nicht auf internen Code angewiesen sind, können Sie die [python 2.7-Implementierung von EnvironmentVarGuard] (https://github.com/python/cpython/blob/2.7/Lib/test/test_support) kopieren .py # L957-L1001) in Ihren eigenen Code - es ist ziemlich einfach. – medmunds

0

Ich verwende py.test als meine Test-Runner, und es ermöglicht Ihnen, eine pytest.ini Datei zu erstellen, in der Sie eine bestimmte Einstellungsdatei angeben können, während Tests ausgeführt werden.

Siehe Dokumentation zu diesem Thema hier:

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

Ich empfehle py.test allgemein als Testläufer, weil es verschiedene Arten von Testklassen und sogar einfacher Funktionen unterstützt, und es ist ziemlich einfach zu installieren up Fixtures oder anderen Code, der vor und nach Tests ausgeführt wird.

+0

So ändern Sie 'settings.py' Dateien, keine Umgebungsvariablen. Meine API-Aufrufe, beispielsweise nach AWS usw., werden mit Konstruktoren erstellt, die nach Umgebungsvariablen und nicht nach django-Einstellungen suchen. – lollercoaster

+0

Sie haben gesagt: "Es gibt Möglichkeiten, Einstellungen während des Tests außer Kraft zu setzen, aber ich möchte nicht, dass sie in settings.py definiert sind, da dies ein Sicherheitsproblem darstellt." Ich sehe nicht, wie das Definieren von Variablen in einer Einstellungsdatei, die * nur * von Ihrem Test-Runner verwendet wird, ein Sicherheitsproblem darstellt. – erewok

+0

Ich hätte klarer sein sollen. Es gibt zwei Probleme. 1) Sicherheit, keine Anmeldeinformationen, 2) mein Workflow mit 'Boto' und anderen APIs verwendet Umgebungsvariablen, so dass ich diese verwenden möchte. Ich habe nur die Analogie mit settings.py gezeichnet – lollercoaster

0

Alte Frage, aber es erschien in einer Google-Suche und keine der vorhandenen Antworten sind geeignet. Wenn Sie pytest verwenden, kann env vars mit pytest's monkeypatching functionality eingestellt/wiederhergestellt werden.

13

Die test.support.EnvironmentVarGuard ist eine interne API, die von Version zu Version mit brechenden (rückwärtskompatiblen) Änderungen geändert werden kann. In der Tat ist das gesamte test Paket nur für den internen Gebrauch. Auf der Dokumentationsseite des Testpakets wurde ausdrücklich angegeben, dass es sich um ein internes Testen von Kernbibliotheken und KEINE öffentliche API handelt. (siehe Links unten)

Sie sollten patch.dict() in Python Standard lib unittest.mock verwenden. Es kann als Kontextmanager, Dekorator oder Klassendekorator verwendet werden. Siehe den folgenden 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 nicht in der Dokumentation gründlich liest und könnte die Note verpasst haben, lesen Sie mehr test Paket Noten

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

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

+2

@seb in der Verbindung, die Sie zur Verfügung gestellt haben, ist es in 'class test.test_support.EnvironmentVarGuard' verankert, mit anderen Worten, es ist Teil des' test' -Pakets, welches ein Regressionstestpaket für ** Python ** ist. Und dann scrollen Sie Ihre Seite ALLES WEG, lesen Sie die Notiz in der zweiten Zeile direkt nach dem Titel: _Hinweis Das Testpaket ist nur für den internen Gebrauch von Python gedacht. Es ist dokumentiert zugunsten der Kernentwickler von Python. Jegliche Verwendung dieses Pakets außerhalb der Python-Standardbibliothek wird nicht empfohlen, da sich der hier erwähnte Code zwischen den Python-Versionen ohne Ankündigung ändern oder entfernen kann. – Devy

1

Wenn Sie Laden Sie Ihre Umgebungsvariablen in Django Datei wie folgt:
import os ENV_NAME = os.environ.get('ENV_NAME', 'default')
Sie könnten so:
from django.test import TestCase, override_settings @override_settings(ENV_NAME="super_setting") def test_...(self):