django impostazione delle variabili di ambiente in unittest test

Voglio essere in grado di impostare le variabili di ambiente nel mio app Django per i test, per essere in grado di eseguire. Per esempio, le mie opinioni si basano su diverse chiavi API.

Ci sono modi per eseguire l’override delle impostazioni durante i test, ma non li voglio definito in settings.py che è un problema di sicurezza.

Ho provato nella mia funzione di impostazione per impostare le variabili di ambiente, ma che non funziona a dare l’applicazione Django valori.

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

Quando I test in locale, ho semplicemente un .env file che ho eseguito con

foreman start -e .env web

che fornisce os.environ con valori. Ma in Django unittest.TestCase non hanno un modo (che io sappia) per impostare.

Come posso ottenere intorno a questo?

 

7 Replies
  1. 33

    Il test.support.EnvironmentVarGuard interno API che si possa cambiare da versione a versione con la rottura (non compatibili) modifiche. Infatti, l’intero test pacchetto è solo per uso interno. E ‘ stato esplicitamente dichiarato sul pacchetto di test pagina di documentazione che è per il testing interno di librerie principali e NON una API pubblica. (vedi link qui sotto)

    Si dovrebbe usare patch.dict() in python lib unittest.mock. Può essere usato come un contesto manager, decoratore o classe di decoratore. Vedere l’esempio di codice riportato di seguito copiata dal sito ufficiale documentazione di 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

    Aggiornamento: per chi non leggere la documentazione a fondo e potrebbe mancare la nota, per saperne di più test pacchetto di note a

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

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

    • nel link che hai fornito, è ancorato a class test.test_support.EnvironmentVarGuard, in altre parole, è parte del test pacchetto, che è un test di regressione pacchetto per Python. E poi scorrere la pagina FINO, a leggere la nota nella seconda riga a destra dopo il titolo: Nota Il pacchetto di test è pensato per uso interno da Python solo. È documentata per il beneficio dei principali sviluppatori di Python. Qualsiasi utilizzo di questo pacchetto al di fuori di Python standard library è sconsigliato come codice qui menzionati possono essere modificati o rimossi senza preavviso tra le versioni di Python.
  2. 14

    Come @schillingt notato nei commenti, EnvironmentVarGuard era il modo corretto.

    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

    Questa imposta correttamente le variabili di ambiente per tutta la durata del contesto oggetto with istruzione.

    • Genera un errore di importazione. Inoltre, la documentazione per EnvironmentVarGuard afferma: “Attenzione Il pacchetto di test è pensato per uso interno da Python solo. È documentata per il beneficio dei principali sviluppatori di Python. Qualsiasi utilizzo di questo pacchetto al di fuori di Python standard library è sconsigliato come codice qui menzionati possono essere modificati o rimossi senza preavviso tra le versioni di Python.”
    • python 3 spostato from test.support import EnvironmentVarGuard. Tuttavia, se si preferisce non dipendono solo uso interno codice, è possibile copiare il python 2.7 attuazione di EnvironmentVarGuard nel tuo codice, e ‘ abbastanza semplice.
  3. 5

    Utilizzando EnvironmentVarGuard non è una buona soluzione in quanto non in alcuni ambienti e le opere di altri. si veda l’esempio sotto.

    django impostazione delle variabili di ambiente in unittest test

    Una soluzione migliore è quello che è stato suggerito da erewok che richiede l’uso del unittest.mock in python3.

    Supponendo che utilizza 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')

  4. 3

    Se si sta caricando le variabili di ambiente in Django settings.py file come questo:

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

    Si potrebbe usare questo:

    from django.test import TestCase, override_settings
    
    @override_settings(ENV_NAME="super_setting")
    def test_...(self):
    • Questa è una buona risposta in quanto è una pratica comune per tirare os.environ variabili in settings.py, e quindi utilizzare quelli variabili (a-la from django.conf import settings) tutto il codice. Se il codice utilizza, per esempio, my_obj = MyClass(arg=settings.MY_ENV_VAR), allora si avrà bisogno di utilizzare il @override_settings() wrapper per impostare correttamente il tuo MY_ENV_VAR in unità di test. Se si imposta la vostra os.environ vars in qualsiasi altro modo, my_obj non verrà istanziato correttamente
  5. 1

    Io uso py.test come il mio test runner, e permette di creare un pytest.ini file in cui è possibile specificare un file di impostazioni da utilizzare durante l’esecuzione di test.

    Vedere la documentazione su questo qui:

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

    Mi raccomando py.prova, in generale, come un test runner, perché supporta diversi tipi di test di classi e anche di semplici funzioni, ed è abbastanza facile da impostare infissi o altro codice che viene eseguito prima e dopo il test.

    • Questo è il modo per modificare settings.py file, non di variabili di ambiente. Le mie chiamate API, per esempio AWS, ecc sono fatti con i costruttori per la ricerca di variabili di ambiente, non django impostazioni.
    • Lei ha detto, “Ci sono molti modi per eseguire l’override delle impostazioni durante la fase di test, ma non li voglio definito in settings.py come che è un problema di sicurezza.” Non vedo come la definizione di variabili in un file di impostazioni che è usato solo per il test runner è un problema di sicurezza.
    • Avrei dovuto essere più chiaro. Ci sono due problemi. 1) la sicurezza, non commettere credenziali, 2) il mio flusso di lavoro con boto e altre Api inutilizzate le variabili di ambiente, così mi piacerebbe essere in grado di utilizzare tali. Ero solo disegno l’analogia con settings.py
    • I test stanno andando a utilizzare effettivo chiavi API e le credenziali? Si sta effettivamente andando a comunicare con terze parti Api?
    • Sì, assolutamente. È piuttosto difficile verificare se un S3 secchio è scrivibile, ecc senza l’utilizzo di API di credenziali.
    • Non ho mai considerato il test di terze parti Api.
    • No, non prova 3rd party Api. Si esegue il test di configurazione di servizi a terzi, le Api e se l’interfaccia con le Api che hai impostato funziona come previsto, con tutti i casi di angolo. Questo è più che accettabile pratica, sarebbe folle non.
    • A parte la configurazione, in genere, si prova il codice dell’applicazione che comunica con le Api che utilizzano deriso interfacce. Non credo che vorrei il mio ic-server, effettuare le chiamate alle Api. Non voglio che accidentalmente l’invio di e-mail o parlare al mondo in altri modi.

  6. 0

    Inizialmente la mia variabile env PARTNER_CODE è stato impostato per wow.

    Ho potuto in grado di modificare la variabile env utilizzando il seguente:

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

    Ora la mia variabile env PARTNER_CODE dice sos.

Lascia un commento