gpt4 book ai didi

python - 如何在 pytest 中使用 monkeypatch 或 mock 删除库?

转载 作者:行者123 更新时间:2023-12-05 03:49:35 24 4
gpt4 key购买 nike

如果我的库有一个 contrib extra,其中有依赖项(比如 requests),我希望用户必须安装才能访问 CLI API,但是我在 CI 测试期间安装了 contrib extra 如何使用 pytest's MonkeyPatch在测试期间删除依赖项以确保我的检测是正确的?

例如,如果 contrib extra 将另外安装 requests ,所以我希望用户必须这样做

$ python -m pip install mylib[contrib]

然后能够在命令行上有一个看起来像的 CLI API

$ mylib contrib myfunction

myfunction 使用 requests 依赖

# mylib/src/mylib/cli/contrib.py
import click
try:
import requests
except ModuleNotFoundError:
pass # should probably warn though, but this is just an example

# ...

@click.group(name="contrib")
def cli():
"""
Contrib experimental operations.
"""

@cli.command()
@click.argument("example", default="-")
def myfunction(example):
requests.get(example)
# ...

如何在我的 pytest 测试中模拟或 monkeypatch out requests 以确保用户会正确收到警告连同 ModuleNotFoundError 如果他们这样做了

$ python -m pip install mylib
$ mylib contrib myfunction

?在阅读了有关 pytest 标签的其他一些问题后,我认为我仍然不明白该怎么做,所以我在这里问。

最佳答案

我最终所做的是有效的,而且我已经确认这是一个合理的方法 thanks to Anthony Sottile , 是通过在 sys.modules 中将其设置为 None 然后重新加载模块来模拟不存在额外的依赖项(此处为 requests) (s) 需要使用 requests。我测试有一个实际的投诉,即 requests 不存在,无法使用 caplog 导入。

这是我目前正在使用的测试(名称已更改以匹配我在上述问题中的玩具示例问题)

import mylib
import sys
import logging
import pytest
from unittest import mock
from importlib import reload
from importlib import import_module

# ...

def test_missing_contrib_extra(caplog):
with mock.patch.dict(sys.modules):
sys.modules["requests"] = None
if "mylib.contrib.utils" in sys.modules:
reload(sys.modules["mylib.contrib.utils"])
else:
import_module("mylib.cli")

with caplog.at_level(logging.ERROR):
# The 2nd and 3rd lines check for an error message that mylib throws
for line in [
"import of requests halted; None in sys.modules",
"Installation of the contrib extra is required to use mylib.contrib.utils.download",
"Please install with: python -m pip install mylib[contrib]",
]:
assert line in caplog.text
caplog.clear()

我应该注意到,这实际上是在 @Abhyudai's answer to "Test for import of optional dependencies in init.py with pytest: Python 3.5 /3.6 differs in behaviour" 中提倡的。 @hoefling 链接到上面(在我解决这个问题之后但在我开始发布之前发布)。

如果人们有兴趣在实际的图书馆中看到这个,c.f.以下两个 PR:

注意事项:Anthony Sottile 警告说

reload() can be kinda iffy -- I'd be careful with it (things which have old references to the old module will live on, sometimes it can introduce new copies of singletons (doubletons? tripletons?)) -- I've tracked down many-a-test-pollution problems to reload()

因此,如果我实现更安全的替代方案,我将修改此答案。

关于python - 如何在 pytest 中使用 monkeypatch 或 mock 删除库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63865618/

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