如何提高@patch和MagicMock语句的可读性和可维护性(避免长名称和字符串标识)?

2024-03-30

在我的测试代码中,我有很多样板表达式“Magic”、“return_”。我还有很长的字符串来标识要模拟的函数的路径。 重构期间不会自动替换字符串,我更愿意直接使用导入的函数。

示例代码:

from mock import patch, MagicMock
from pytest import raises

@patch(
    'foo.baa.qux.long_module_name.calculation.energy_intensity.intensity_table',
    MagicMock(return_value='mocked_result_table'),
)

相反,我更喜欢:

from better_test_module import patch, Mock, raises
from foo.baa.qux.long_module_name.calculation import energy_intensity

@patch(
    energy_intensity.intensity_table,
    Mock('mocked_result_table'),
)

or

@patch(
    energy_intensity.intensity_table,
    'mocked_result_table',
)

我将相应的自定义实现作为答案发布在下面。

如果您有其他建议,请告诉我。我想知道为什么建议的解决方案不是默认的。我不想重新发明轮子。 因此,如果有我可以使用的现有库,请告诉我。

Related:

Mock 与 MagicMock https://stackoverflow.com/questions/17181687/mock-vs-magicmock

如何在 MagicMock 子类上重写 __getitem__ https://stackoverflow.com/questions/67580353/how-to-override-getitem-on-a-magicmock-subclass


创建一个包装器模块,允许使用较短的名称并直接传递函数。 (如果类似的东西已经作为 pip 包存在,请告诉我;不想重新发明轮子。)

Usage:

from my_test_utils.mock import patch, Mock, raises    
from foo.baa.qux.long_module_name.calculation import energy_intensity

@patch(
    energy_intensity.intensity_table,
    Mock('mocked_result_table'),  
)

我的包装代码的初稿my_test_utils/mock.py:

from mock import MagicMock, DEFAULT
from mock import patch as original_patch
from pytest import raises as original_raises


class Mock(MagicMock):
    # This class serves as a wrapper for MagicMock to allow for shorter syntax

    def __new__(cls, *args, **kwargs):
        if len(args) > 0:
            first_argument = args[0]
            mock = MagicMock(return_value=first_argument, *args[1:], **kwargs)
        else:
            mock = MagicMock(**kwargs)
        return mock

    def assert_called_once(self, *args, **kwargs):  # pylint: disable = useless-parent-delegation
        # pylint did not find this method without defining it as a proxy
        super().assert_called_once(*args, **kwargs)

    def assert_not_called(self, *args, **kwargs):  # pylint: disable = useless-parent-delegation
        # pylint did not find this method without defining it as a proxy
        super().assert_not_called(*args, **kwargs)


def patch(item_to_patch, *args, **kwargs):
    if isinstance(item_to_patch, str):
            raise KeyError('Please import and use items directly instead of passing string paths!')

    module_path = item_to_patch.__module__
    if hasattr(item_to_patch, '__qualname__'):
        item_path = module_path + '.' + item_to_patch.__qualname__
    else:
        name = _try_to_get_object_name(item_to_patch, module_path)
        item_path = module_path + '.' + name

    item_path = item_path.lstrip('_')

    return original_patch(item_path, *args, **kwargs)


def _try_to_get_object_name(object_to_patch, module_path):
    module = __import__(module_path)
    name = None
    for attribute_name in dir(module):
        attribute = getattr(module, attribute_name)
        if attribute == object_to_patch:
            if name is None:
                name = attribute_name
            else:
                # object is not unique within its parent but used twice
                message = (
                    'Could not identify item to patch because object is not unique.'
                    + ' Please use a unique string path.'
                )
                raise KeyError(message)
    if name is None:
        raise KeyError('Could not identify object to patch.')
    return name
    



def raises(*args):
    # This function serves as a wrapper for raises to be able to import it from the same module as the other functions
    return original_raises(*args)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何提高@patch和MagicMock语句的可读性和可维护性(避免长名称和字符串标识)? 的相关文章

  • Django 是否使用一个线程来处理 WSGI 或 Gunicorn 中的多个请求?

    根据标题 我想知道 Django 在通过 WSGI 或 Gunicorn 运行时是否使用一个线程来处理多个请求 我知道从不应该访问的地方访问请求是一种不好的做法 但我仍然想这样做 我认为有充分的理由 例如在我的自定义模板加载器中访问当前用户
  • C# 模拟接口与模拟类

    我是 net 中的最小起订量框架的新手 根据我的在线研究 似乎有两种方法可以使用这个框架 要么模拟接口 要么模拟具体类 似乎在嘲笑具体类时 只有virtual方法可以被嘲笑 就我而言 我只想模拟实现接口的类的几个方法 例如 如果我们有以下内
  • 用于在 Windows 中自动执行桌面活动的 Python 代码

    我想使用 Python 在 Windows 环境中自动化桌面活动 怎样才能做到呢 一些例子也会有帮助 我所说的桌面活动是指控制鼠标和键盘 访问活动窗口属性 双击桌面上的图标 最小化和最大化窗口 通过键盘向输入弹出窗口输入数据等操作 看一下S
  • 无法在 python 中导入名称 GoogleMaps

    我使用下面的代码来获取地址的纬度和经度 from googlemaps import GoogleMaps gmaps GoogleMaps api key address Constitution Ave NW 10th St NW Wa
  • 有没有办法清理 jinja2 生成的 html?

    我们使用 jinja2 来创建 html 但是 由于我们在 jinja 中执行许多循环和其他操作来生成 html 所以 html 看起来 很丑 注意 这只是为了美观 我们可以做些什么来清理 html 吗 除了清理我们的 jinja2 代码之
  • 在 pandas 数据框中按列应用 Seaborn 热图

    我试图在枢轴熊猫数据帧上使用seaborn的热图 就像在超链接中一样有效 df pd DataFrame np random randint 1 100 size 3 2 df columns A B df sns heatmap df a
  • 如何使用scrapy抓取xml url

    你好 我正在使用 scrapy 来抓取 xml url 假设下面是我的 Spider py 代码 class TestSpider BaseSpider name test allowed domains www example com s
  • 根据两个预先计算的直方图报告两个样本的 K-S 统计量

    Problem 在这里 我绘制了存储在文本文件中的 2 个数据集 在列表中 dataset 每个包含 218 亿个数据点 这使得数据太大而无法作为数组保存在内存中 我仍然能够将它们绘制为直方图 但我不确定如何通过2 样本KS测试 http
  • PyQt:如何设置组合框项目可检查?

    为了将 GUI 小部件数量保持在最低限度 我需要找到一种方法来为用户提供下拉菜单项的选择 这些菜单项可用于过滤掉 listWidget 项中显示的内容 假设 listWidget 列出了 5 个不同类别的项目 Cat A Cat B Cat
  • SQLAlchemy+pymysql 错误:sqlalchemy.util.queue.Empty

    尝试使用 Eclispse 在 Ubuntu 上运行 Python 2 SQLAlchemy 0 8 和 MySQL5 2 但我不断收到以下错误 我使用 pymysql 实际上是 pymysql3 引擎 模块监视器 from sqlalch
  • 使用 Python 读取 App Engine 上的文件?

    是否可以在 GAE 上打开文件来读取其内容并获取最后修改的标签 我收到 IOError Errno 13 文件无法访问 我知道我无法删除或更新 但我相信阅读应该是可能的 有人遇到过类似的问题吗 os stat f r st mtim 您可能
  • SQLAlchemy - 如何使用 SQLAlchemy 做出“django 选择”?

    在 Django 中 我们可以使用非常简单的 选择 例如 GENDER CHOICES M Male F Female class Foo models Model gender models CharField max length 1
  • 如何在海龟图形中将多个按键绑定在一起?

    我正在尝试制作一个连接点的 python 游戏 我希望游戏记录 2 次按钮按下操作 示例 如果用户按向上和向右箭头键 乌龟将向东北方向移动 45 度 这是我的代码 import turtle flynn turtle Turtle win
  • python 没有名为serial的模块

    我的 python 程序有问题 我编写了程序来将数据 温度 从 arduino 获取到我的树莓派 sqlite 数据库 但它在第 4 行 导入串行 处给了我一个错误 提示 ImportError 没有名为串行的模块 我使用 python3
  • 如何编辑 QProgressBar 的样式表

    我无法在我的应用程序中编辑进度条的颜色 仅编辑文本颜色 pyhton 3 9 PySide6 QT Creator 7 0 2 Python应用程序 https i stack imgur com 6hKFI png import sys
  • Tornado:DummyFuture 不支持结果阻塞

    我试图获得一个非常简单的初始服务器 它可以 异步 获取 url 来工作 但它会抛出 Exception DummyFuture does not support blocking for results 有这个SO https stacko
  • 将 celery 与 Flask 应用程序上下文一起使用会导致“弹出错误的应用程序上下文”。断言错误

    我或多或少使用设置来使用您的 Flask 应用程序上下文来运行 Celery 任务 http flask pocoo org docs 0 10 patterns celery http flask pocoo org docs 0 10
  • 从多个大型 NetCDF 文件中提取数据的快速/高效方法

    我只需要从全局网格中提取特定节点集的数据 由纬度 经度坐标 按 5000 10000 的顺序 给出 这些数据是水力参数的时间序列 例如波高 全局数据集很大 因此分为许多 NetCDF 文件 每个 NetCDF 文件大小约为 5GB 包含整个
  • 是否可以存根实体框架上下文和类来测试数据访问层?

    我熟悉用于测试 ASP NET MVC 应用程序中的控制器和业务逻辑的技术 我们的应用程序中的数据访问集中在松散耦合的特殊服务中 使用接口并通过实体框架与实际数据库一起使用 然而 随着 DAL 变得越来越复杂 隐藏数据库实现细节并为应用程序
  • Python中矩阵元素的双重求和

    基于下面的简化示例 我想在我的代码中 from sympy import import numpy as np init printing x y symbols x y mat Matrix x 1 1 y X 1 2 3 Y 10 20

随机推荐