遗留代码:如何使用 pytest 测试全局变量的值

Legacy code: how to test values of global variables with pytest

免责声明: 这个问题只是关于在现有代码库(遗留代码)中测试全局变量。 不要对新代码使用全局变量,因为(除其他原因外)这会使测试变得更加困难

我正在处理一些非常依赖全局变量的遗留代码。

这个遗留代码有一个调用其他函数的主函数,那些嵌套函数改变了全局的值。

我想通过开始对主调用函数进行测试并重构嵌套函数来重构所有这些。 为此,我想在调用主函数后检查全局变量的值。

然而,我无法让它在pytest中运行,这是我的两次尝试:

尝试

文件夹结构:

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

但是,当我 运行 使用 python -m pytest 时,我得到:

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

如您所见,全局变量实际上从未改变,我希望这些测试能够通过

我正在使用 python 3.9.5 和 pytest 6.2.4。

您不能像那样导入变量,因为在分配给它们时您会丢失对它们的引用。您打算这样做:

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