使用 pytest 测试常量声明
Testing constants declarations using pytest
我们有一个 Python 3.7 应用程序,其声明的 constants.py 文件具有以下形式:
APP_CONSTANT_1 = os.environ.get('app-constant-1-value')
在 test.py 中,我们希望使用类似这样的东西来测试这些常量的设置(这是高度简化但代表核心问题):
class TestConfig:
"""General config tests"""
@pytest.fixture
def mock_os_environ(self, monkeypatch):
""" """
def mock_get(*args, **kwargs):
return 'test_config_value'
monkeypatch.setattr(os.environ, "get", mock_get)
def test_mock_env_vars(self, mock_os_environ):
import constants
assert os.environ.get('app-constant-1-value') == 'test_config_value' #passes
assert constants.APP_CONSTANT_1 == 'test_config_value' #fails
第二个断言失败,因为 constants.constants。APP_CONSTANT_1 是 None。事实证明 constants.py 似乎是在 pytest 的 'collecting' 阶段加载的,因此在测试 运行.
时已经设置好了
我们在这里缺少什么?我觉得在 pytest 中有一种简单的方法可以解决这个问题,但还没有发现秘密。有什么方法可以避免在测试 运行 之前加载常量文件吗?任何想法表示赞赏。
嗯,我会避免使用常量。您可以先使用 subclass os.environment,然后使用模拟的 subclass 进行单元测试,这样您就可以将 my_env.unique_env 作为成员变量。然后你可以使用例如。 import json 使用 json 配置文件而不涉及硬编码 python.
然后 subclass 可以保存相关变量(或者方法,如果你愿意的话)
能够向 os.environment 添加外观可为您提供所需的抽象,而不会出现任何问题。
即使是在使用 legacy/larger 项目,使用适配器访问环境的优势也必须显而易见。
由于您正在编写单元测试,因此有机会在测试和被测试的函数中使用适配器 class。
问题很可能是constants
之前加载过。为确保它获得修补后的值,您必须重新加载它:
import os
from importlib import reload
import pytest
import constants
class TestConfig:
"""General config tests"""
@pytest.fixture
def mock_os_environ(self, monkeypatch):
""" """
monkeypatch.setenv('app-constant-1-value', 'test_config_value')
reload(constants)
def test_mock_env_vars(self, mock_os_environ):
assert os.environ.get('app-constant-1-value') == 'test_config_value'
assert app.APP_CONSTANT_1 == 'test_config_value'
请注意,我使用monkeypatch.setenv
专门设置了您需要的变量。如果不需要更改所有环境变量,这个比较好用。
我们有一个 Python 3.7 应用程序,其声明的 constants.py 文件具有以下形式:
APP_CONSTANT_1 = os.environ.get('app-constant-1-value')
在 test.py 中,我们希望使用类似这样的东西来测试这些常量的设置(这是高度简化但代表核心问题):
class TestConfig:
"""General config tests"""
@pytest.fixture
def mock_os_environ(self, monkeypatch):
""" """
def mock_get(*args, **kwargs):
return 'test_config_value'
monkeypatch.setattr(os.environ, "get", mock_get)
def test_mock_env_vars(self, mock_os_environ):
import constants
assert os.environ.get('app-constant-1-value') == 'test_config_value' #passes
assert constants.APP_CONSTANT_1 == 'test_config_value' #fails
第二个断言失败,因为 constants.constants。APP_CONSTANT_1 是 None。事实证明 constants.py 似乎是在 pytest 的 'collecting' 阶段加载的,因此在测试 运行.
时已经设置好了我们在这里缺少什么?我觉得在 pytest 中有一种简单的方法可以解决这个问题,但还没有发现秘密。有什么方法可以避免在测试 运行 之前加载常量文件吗?任何想法表示赞赏。
嗯,我会避免使用常量。您可以先使用 subclass os.environment,然后使用模拟的 subclass 进行单元测试,这样您就可以将 my_env.unique_env 作为成员变量。然后你可以使用例如。 import json 使用 json 配置文件而不涉及硬编码 python.
然后 subclass 可以保存相关变量(或者方法,如果你愿意的话)
能够向 os.environment 添加外观可为您提供所需的抽象,而不会出现任何问题。
即使是在使用 legacy/larger 项目,使用适配器访问环境的优势也必须显而易见。
由于您正在编写单元测试,因此有机会在测试和被测试的函数中使用适配器 class。
问题很可能是constants
之前加载过。为确保它获得修补后的值,您必须重新加载它:
import os
from importlib import reload
import pytest
import constants
class TestConfig:
"""General config tests"""
@pytest.fixture
def mock_os_environ(self, monkeypatch):
""" """
monkeypatch.setenv('app-constant-1-value', 'test_config_value')
reload(constants)
def test_mock_env_vars(self, mock_os_environ):
assert os.environ.get('app-constant-1-value') == 'test_config_value'
assert app.APP_CONSTANT_1 == 'test_config_value'
请注意,我使用monkeypatch.setenv
专门设置了您需要的变量。如果不需要更改所有环境变量,这个比较好用。