2011-06-07 20 views
18

Estoy trabajando en una serie de pruebas unitarias en Python, algunas de las cuales dependen del valor de una variable de configuración. Estas variables se almacenan en un archivo de configuración global de Python y se usan en otros módulos. Me gustaría escribir pruebas unitarias para diferentes valores de las variables de configuración, pero todavía no he encontrado la manera de hacerlo.Modificación de variables globales en Python unittest framework

No tengo la posibilidad de volver a escribir las firmas de los métodos que estoy probando.

Esto es lo que me gustaría lograr:

from my_module import my_function_with_global_var 

class TestSomething(self.unittest): 

    def test_first_case(self): 
     from config import MY_CONFIG_VARIABLE 
     MY_CONFIG_VARIABLE = True 
     self.assertEqual(my_function_with_global_var(), "First result") 

    def test_second_case(self): 
     from config import MY_CONFIG_VARIABLE 
     MY_CONFIG_VARIABLE = False 
     self.assertEqual(my_function_with_global_var(), "Second result") 

Gracias.

Editar: Hizo que el código de ejemplo sea más explícito.

Respuesta

28

No hagas esto:

from my_module import my_function_with_global_var 

Pero esto:

import my_module 

y luego se puede inyectar en el MY_CONFIG_VARIABLEmy_module importados, sin cambiar el sistema que se está probando de esta manera:

class TestSomething(unittest.TestCase): # Fixed that for you! 

    def test_first_case(self): 
     my_module.MY_CONFIG_VARIABLE = True 
     self.assertEqual(my_module.my_function_with_global_var(), "First result") 

    def test_second_case(self): 
     my_module.MY_CONFIG_VARIABLE = False 
     self.assertEqual(my_module.my_function_with_global_var(), "Second result") 

Hice algo similar en my answer toHow can I simulate input to stdin for pyunit?.

+1

Impresionante. Esto de hecho está funcionando. – badzil

+1

@ badzil: excelente. Ahora que tiene cobertura de pruebas unitarias, puede eliminar la (necesidad de) variable global ;-) – Johnsyweb

+1

Ojalá pudiera. – badzil

2

El código importa MY_CONFIG_VARIABLE en el ámbito local e inmediatamente sobrescribe el nombre con un objeto diferente. Eso no cambiará el valor en el módulo config. Pruebe

import config 
config.MY_CONFIG_VARIABLE = False 

en su lugar.

+1

Tal vez se me olvidó mencionar algo más. Las funciones que estoy probando están en un módulo separado y, por lo tanto, ya han importado la variable global que necesito modificar. La modificación propuesta solo modifica la variable global en el archivo de prueba. – badzil

+0

@badzil: Probablemente la mejor opción es no utilizar 'from config import MY_CONFIG_VARIABLE' en los módulos que está probando, sino' import config' y acceder a las variables como 'config.MY_CONFIG_VARIABLE'. –

+0

Gracias. Esto funciona aunque estaba buscando no modificar el módulo que estoy probando. Supongo que como el módulo para probar usa la directiva import ... from ..., no hay forma de cambiar el valor de la variable global después de la importación. – badzil

27

Probablemente quiera burlarse de esas variables globales. La ventaja de esto es que los globales se reinician una vez que hayas terminado. Python se envía con un módulo de burla que le permite hacer esto.

unittest.mock.patch usarse como decorador:

class TestSomething(self.unittest): 

    @patch('config.MY_CONFIG_VARIABLE', True) 
    def test_first_case(self): 
     self.assertEqual(my_function_with_global_var(), "First result") 

También puede utilizarlo como un gestor de contexto:

def test_first_case(self): 
     with patch('config.MY_CONFIG_VARIABLE', True): 
      self.assertEqual(my_function_with_global_var(), "First result") 
+0

Enfoque fantástico: simple y efectivo. Gracias por compartir. Especialmente útil con la edición de @Michele. – fedorqui

+0

En mi caso, no me importó el valor inicial, pero necesitaba verificar que se haya escrito el mensaje global. Eso es posible usando 'con patch ('config') como mock_config' y' self.assertEqual (True, mock_config.MY_CONFIG_VARIABLE) ' – codehearts