web-dev-qa-db-fra.com

Modification des variables globales dans Python framework unittest

Je travaille sur une série de tests unitaires en Python, dont certains dépendent de la valeur d'une variable de configuration. Ces variables sont stockées dans un fichier de configuration global Python et sont utilisées dans d'autres modules. Je voudrais écrire des tests unitaires pour différentes valeurs des variables de configuration mais je n'ai pas encore trouvé de moyen de le faire .

Je n'ai pas la possibilité de réécrire les signatures des méthodes que je teste.

Voici ce que j'aimerais réaliser:

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")

Merci.

Edit: rendu l'exemple de code plus explicite.

36
badzil

Utilisez unittest.mock.patch Comme dans réponse de @ Flimm , si vous en avez la possibilité.


Réponse originale

Ne faites pas ça:

from my_module import my_function_with_global_var

Mais ça:

import my_module

Et puis vous pouvez injecter MY_CONFIG_VARIABLE Dans le my_module Importé, sans changer le système testé comme ceci:

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")

J'ai fait quelque chose de similaire dans ma réponse àComment puis-je simuler l'entrée de stdin pour pyunit? .

47
Johnsyweb

Vous voudrez probablement vous moquer de ces variables globales à la place. L'avantage de ceci est que les globaux sont réinitialisés une fois que vous avez terminé. Python est livré avec un module moqueur qui vous permet de le faire.

unittest.mock.patch être utilisé comme décorateur:

class TestSomething(self.unittest):

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

Vous pouvez également l'utiliser comme gestionnaire de contexte:

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

Vous codez les importations MY_CONFIG_VARIABLE dans la portée locale, puis écrase immédiatement le nom avec un autre objet. Cela ne changera pas la valeur dans le module config. Essayer

import config
config.MY_CONFIG_VARIABLE = False

au lieu.

2
Sven Marnach