Modifying global variables in Python unittest framework
I am working on a series of unit tests in Python, some of which depend on the value of a configuration variable. These variables are stored in a global Python config file and are used in other modules. I would like to write unit tests for different values of the configuration variables but have not yet found a way to do this.
I do not have the possibility to rewrite the signatures of the methods I'm testing.
This is what I would like to achieve:
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")
Thanks.
Edit: Made the example code more explicite.
You probably want to mock those global variables instead. The advantage of this is that the globals get reset once you're done. Python ships with a mocking module that lets you do this.
unittest.mock.patch
be used as a decorator:
class TestSomething(self.unittest):
@patch('config.MY_CONFIG_VARIABLE', True)
def test_first_case(self):
self.assertEqual(my_function_with_global_var(), "First result")
You can also use it as a context manager:
def test_first_case(self):
with patch('config.MY_CONFIG_VARIABLE', True):
self.assertEqual(my_function_with_global_var(), "First result")
Use unittest.mock.patch
as in @Flimm's answer, if that's available to you.
Original Answer
Don't do this:
from my_module import my_function_with_global_var
But this:
import my_module
And then you can inject MY_CONFIG_VARIABLE
into the imported my_module
, without changing the system under test like so:
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")
I did something similar in my answer to How can I simulate input to stdin for pyunit? .