在Python unittest框架中修改全局变量

bad*_*zil 38 python unit-testing global-variables

我正在使用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")
Run Code Online (Sandbox Code Playgroud)

谢谢.

编辑:使示例代码更明确.

Fli*_*imm 66

您可能想要模拟这些全局变量.这样做的好处是全局变量一旦完成就会重置.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")
Run Code Online (Sandbox Code Playgroud)

您还可以将其用作上下文管理器:

    def test_first_case(self):
        with patch('config.MY_CONFIG_VARIABLE', True):
            self.assertEqual(my_function_with_global_var(), "First result")
Run Code Online (Sandbox Code Playgroud)


Joh*_*web 48

如果你可以使用unittest.mock.patch,请在@Flimm的答案中使用.


原始答案

不要这样做:

from my_module import my_function_with_global_var
Run Code Online (Sandbox Code Playgroud)

但是这个:

import my_module
Run Code Online (Sandbox Code Playgroud)

然后你可以注入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")
Run Code Online (Sandbox Code Playgroud)

我的回答中 我做了类似的事情如何模拟输入到stdin的pyunit?.

  • 这种方法可以让您了解一个微妙的错误,因为在测试完成时,不会重置"my_module.MY_CONFIG_VARIABLE"的值.如果后续测试在同一进程中运行,则使用"MY_CONFIG_VARIABLE"而不期望它被更改,您的测试可能会失败或根据它们执行的顺序传递. (22认同)
  • 你是对的.这是微妙但主要的缺点,并不是我在2017年做事的方式.我不确定mock.patch甚至在2011年写了这个答案后用Python附带. (6认同)