Reputation: 1403
DISCLAIMER: This question is only about testing global variables in a existing code base (legacy code). Do not use global variables for new code, as (among many other reasons) it makes it more difficult to test
I am dealing with some legacy code that relies a lot on global variables.
This legacy code has a main function that are calling other functions, those nested functions changing the values of the global.
I want to refactor all of that by starting to put a test on the main calling function and refactoring the nested ones. To do so, I want to check the values of the global variables after the call to the main function.
However, I cannot make it work in pytest, here are my two attempts:
Folder structure:
legacy_code.py:
GLOBAL_LIST = None
def add_to_global_list(data: str):
global GLOBAL_LIST
if GLOBAL_LIST is None:
GLOBAL_LIST = [data]
else:
GLOBAL_LIST.append(data)
conftest.py:
import pytest
from src.legacy_code import GLOBAL_LIST
@pytest.fixture(scope="function")
def GLOBAL_VAR():
yield GLOBAL_LIST
test_legacy_code_attempt1.py:
from src.legacy_code import add_to_global_list, GLOBAL_LIST
def test_global_list():
# global GLOBAL_LIST # I tried with or without this line, the result is the same
assert GLOBAL_LIST is None
add_to_global_list("one input")
assert len(GLOBAL_LIST) == 1
test_legacy_code_attempt2.py:
from src.legacy_code import add_to_global_list
def test_global_list(GLOBAL_VAR):
assert GLOBAL_VAR is None
add_to_global_list("one input")
assert len(GLOBAL_VAR) == 1
However, when I run that with python -m pytest
I get :
def test_global_list():
assert GLOBAL_LIST is None
add_to_global_list("one input")
> assert len(GLOBAL_LIST) == 1
E TypeError: object of type 'NoneType' has no len()
tests\test_legacy_code_attempt1.py:10: TypeError
GLOBAL_VAR = None
def test_global_list(GLOBAL_VAR):
assert GLOBAL_VAR is None
add_to_global_list("one input")
> assert len(GLOBAL_VAR) == 1
E TypeError: object of type 'NoneType' has no len()
tests\test_legacy_code_attempt2.py:10: TypeError
FAILED tests/test_legacy_code_attempt1.py::test_global_list - TypeError: object of type 'NoneType' has no len()
FAILED tests/test_legacy_code_attempt2.py::test_global_list - TypeError: object of type 'NoneType' has no len()
As you see, the global variable is actually never changed and I would expect these tests to pass
I am using python 3.9.5 and pytest 6.2.4.
Upvotes: 1
Views: 417
Reputation: 39414
You cannot import variables like that because you lose the reference to them when they are assigned to. You meant to do this:
from src import legacy_code
def test_global_list():
assert legacy_code.GLOBAL_LIST is None
...
# use legacy_code.GLOBAL_LIST wherever you need to
Upvotes: 1