gpt4 book ai didi

python - 如何测试可以用环境变量初始化的数据类?

转载 作者:行者123 更新时间:2023-12-02 01:30:20 25 4
gpt4 key购买 nike

我有以下数据类:

import os
import dataclasses

@dataclasses.dataclass
class Example:
host: str = os.environ.get('SERVICE_HOST', 'localhost')
port: str = os.environ.get('SERVICE_PORT', 30650)

如何为此编写测试?我尝试了以下看起来应该有效的方法:

from stackoverflow import Example
import os


def test_example(monkeypatch):
# GIVEN environment variables are set for host and port
monkeypatch.setenv('SERVICE_HOST', 'server.example.com')
monkeypatch.setenv('SERVICE_PORT', '12345')
# AND a class instance is initialized without specifying a host or port
example = Example()
# THEN the instance should reflect the host and port specified in the environment variables
assert example.host == 'server.example.com'
assert example.port == '12345'

但这失败了:

====================================================================== test session starts ======================================================================
platform linux -- Python 3.8.12, pytest-7.1.2, pluggy-1.0.0
rootdir: /home/biogeek/tmp
collected 1 item

test_example.py F [100%]

=========================================================================== FAILURES ============================================================================
_________________________________________________________________________ test_example __________________________________________________________________________

monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f39de559220>

def test_example(monkeypatch):
# GIVEN environment variables are set for host and port
monkeypatch.setenv('SERVICE_HOST', 'server.example.com')
monkeypatch.setenv('SERVICE_PORT', '12345')
# AND a class instance is initialized without specifying a host or port
example = Example()
# THEN the instance should reflect the host and port specified in the environment variables
> assert example.host == 'server.example.com'
E AssertionError: assert 'localhost' == 'server.example.com'
E - server.example.com
E + localhost

test_example.py:12: AssertionError
==================================================================== short test summary info ====================================================================
FAILED test_example.py::test_example - AssertionError: assert 'localhost' == 'server.example.com'
======================================================================= 1 failed in 0.05s =======================================================================

最佳答案

您的测试失败是因为您的代码在导入模块时加载了环境变量。模块级代码很难测试,因为设置默认值的os.environ.get() 调用在您的测试运行之前已经运行。您必须从 sys.modules 模块缓存中有效地删除您的模块,并且仅在模拟出 os.environ 之后导入您的模块环境变量来测试导入时发生的情况。

您可以改用 dataclass.field()使用 default_factory 参数;每当您创建数据类的实例时,它都会执行可调用以获得默认值:

import os
from dataclasses import dataclass, field
from functools import partial


@dataclass
class Example:
host: str = field(default_factory=partial(os.environ.get, 'SERVICE_HOST', 'localhost'))
port: str = field(default_factory=partial(os.environ.get, 'SERVICE_PORT', '30650'))

我使用了 functools.partial() object创建一个可调用的调用 os.environ.get() 给定的名称和默认值。

请注意,我还将 SERVICE_PORT 的默认值更改为字符串;毕竟,port 字段被注释为 str,而不是 int。 :-)

如果您必须在导入时从环境变量设置这些默认值,那么您可以让 pytestconftest.py module 中模拟这些环境变量。 ;这些是在导入测试之前导入的,因此您有机会在导入被测模块之前进行调整。但是,这不会让您使用不同的默认值运行多个测试:

# add to conftest.py at the same package level, or higher.

@pytest.fixture(autouse=True, scope="session")
def mock_environment(monkeypatch):
monkeypatch.setenv('SERVICE_HOST', 'server.example.com')
monkeypatch.setenv('SERVICE_PORT', '12345')

上面的 fixture 示例,当放在 conftest.py 中时,会在加载测试之前自动修补您的环境,因此在导入模块之前,这个修补程序在最后自动撤消测试 session 。

关于python - 如何测试可以用环境变量初始化的数据类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73457345/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com