python - 如果未安装可选模块,则测试代码的行为

标签 python unit-testing pytest

我有一个软件包packageA,它对packageB 有一个可选的依赖项。如果安装了 packageB,则用户可以访问一些附加功能。但是,不安装它并不限制 packageA 的使用。

我想编写一个单元(或集成?)测试来检查 packageA 如果未安装 packageB 是否仍然可用...也就是说,它不会意外地为 packagB

抛出一个 ImportError

我的测试是这样写的:

from unittest import mock
import pytest


def test_no_err_if_packageb_not_installed():
    import sys
    sys.modules['packageB'] = mock.MagicMock()
    try:
        from packageA import file_that_uses_packageb  # noqa: F401
    except NameError:
        pytest.fail("packagB dependency found at root level")

如果它被单独调用,这是有效的。但是当它作为测试套件的一部分被调用时,这个测试总是会通过。这是因为 sys.modules 已经由之前的测试填充了导入模块。我尝试先从 sys.modulesdel 包,但这不起作用

编写此测试的正确方法是什么?

使用工作解决方案进行编辑

from unittest import mock
import pytest


def test_no_err_if_packageb_not_installed():
    import sys

    # clear cached modules
    mods = list(sys.modules.keys())
    for mod in mods:
        if 'packageA' in mod or 'packageB' in mod:
            del sys.modules[mod]

    sys.modules['packageB'] = mock.MagicMock()
    try:
        from packageA import file_that_uses_packageb  # noqa: F401
    except NameError:
        pytest.fail("packagB dependency found at root level")

    del sys.modules['packageB']

最佳答案

使用 sys.modules 进行黑客攻击是必经之路。问题是您正在重置 packageB 的导入 - 但实际上,要进行此测试,您还必须重置 file_that_uses_packageb 的导入。

在你的测试设置中尝试 del sys.modules["packageB"], sys.modules["packageA.file_that_uses_packageB"] 你应该已经准备好了。

不要忘记在测试结束时再次重置它们,否则实际使用 packageB 的其他测试将失败。

(被试探性地标记为“重复”答案的答案并没有触及相同的点 - 答案谈到使用 imp.reload,它重置并重新运行模块,好的 - 但是如果需要,将不允许您用模拟替换模块代码)

关于python - 如果未安装可选模块,则测试代码的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60746184/

相关文章:

python - 从时区获取语言环境-python、django、pytz

python - 使用 style_data_conditionals 的 Dash DataTable 单独突出显示效果不寻常

在同一类的另一个方法中调用 C++ GoogleMock 模拟方法

java - 将模拟对象作为 JUnit 参数传递给带参数的测试方法

swift - 如何在 swift 中模拟 realm-cocoa

python - 为什么 `py.test --last-failed` 会跳过许多测试,尽管之前没有测试失败?

python - 密谋:如何在两个子图上使用相同的配色方案?

python - 如何在 Windows 上运行介子构建系统?

python - [py.test] : test dependencies

pyspark - 如何通过将数据帧作为输入来获取 palantir 代工厂中的所有必需值来编写 pytest