Модификация глобальных переменных в инфраструктуре юнит-тестов Python - PullRequest
35 голосов
/ 07 июня 2011

Я работаю над серией модульных тестов в Python, некоторые из которых зависят от значения переменной конфигурации. Эти переменные хранятся в глобальном конфигурационном файле Python и используются в других модулях. Я хотел бы написать модульные тесты для различных значений переменных конфигурации, но пока не нашел способа сделать это.

У меня нет возможности переписать подписи методов, которые я тестирую.

Вот чего я бы хотел достичь:

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

Спасибо.

Редактировать: код примера стал более понятным.

Ответы [ 3 ]

64 голосов
/ 06 января 2016

Вы, вероятно, хотите вместо этого смоделировать эти глобальные переменные. Преимущество этого состоит в том, что глобальные настройки сбрасываются, как только вы закончите. Python поставляется с модулем насмешки, который позволяет вам сделать это.

unittest.mock.patch будет использоваться в качестве декоратора:

class TestSomething(self.unittest):

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

Вы также можете использовать его как менеджер контекста:

    def test_first_case(self):
        with patch('config.MY_CONFIG_VARIABLE', True):
            self.assertEqual(my_function_with_global_var(), "First result")
46 голосов
/ 08 июня 2011

Используйте unittest.mock.patch, как в @ ответе Флимма , если он вам доступен.


Оригинальный ответ

Не делай этого:

from my_module import my_function_with_global_var

Но это:

import my_module

И затем вы можете вставить MY_CONFIG_VARIABLE в импортированный my_module, не изменяя тестируемую систему, например так:

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

Я сделал нечто подобное в моем ответе на Как я могу имитировать ввод в stdin для pyunit? .

2 голосов
/ 07 июня 2011

Вы импортируете код MY_CONFIG_VARIABLE в локальную область, а затем немедленно перезаписываете имя другим объектом.Это не изменит значение в модуле config.Попробуйте вместо

import config
config.MY_CONFIG_VARIABLE = False

.

...