【问题标题】:Testing constants declarations using pytest使用 pytest 测试常量声明
【发布时间】:2021-03-24 13:40:59
【问题描述】:

我们有一个 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 的“收集”阶段加载的,因此在运行测试时已经设置好了。

我们在这里缺少什么?我觉得在 pytest 中有一种简单的方法可以解决这个问题,但还没有发现这个秘密。有什么方法可以避免在测试运行之前加载常量文件?任何想法都表示赞赏。

【问题讨论】:

  • 这对测试没有多大意义,因为您基本上是在测试 os.environ.get 是否有效。

标签: python pytest monkeypatching


【解决方案1】:

问题很可能是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 专门设置了您需要的变量。如果您不需要更改所有环境变量,这更容易使用。

【讨论】:

  • 谢谢一百万!我完全不知道 importlib.reload。完美运行。
【解决方案2】:

呃,我会避免使用常量。您可以先将 os.environment 子类化,然后使用模拟子类进行单元测试,因此您可以将 my_env.unique_env 作为成员变量。然后你可以使用例如。导入 json 以使用 json 配置文件,而不涉及硬编码的 python。

然后子类可以保存相关变量(或方法,如果您愿意)

能够向 os.environment 添加外观为您提供您正在寻找的抽象,而不会出现任何问题。

即使是使用遗留/更大的项目,使用适配器访问环境的优势也必须是显而易见的。

由于您正在编写单元测试,因此有机会在测试和正在测试的函数中使用适配器类。

【讨论】:

  • 谢谢 - 不幸的是,这是一个更大的项目,并且正在进行中。使这种类型的改变不会成功(至少在短期内)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-18
  • 2011-03-11
  • 1970-01-01
相关资源
最近更新 更多