模拟Python可迭代用于Sphinx

时间:2013-12-18 18:54:05

标签: python mocking python-sphinx python-mock

我正在使用Sphinx来记录依赖于wxPython的项目,使用 autodocs 扩展名,以便它会自动从我们的文档字符串生成页面。 autodocs 扩展程序会自动对import的每个模块进行操作,这对我们的软件包来说很好,但是当我们import像wxPython这样的大型外部库时会出现问题。因此,不是让它从wxPython生成所有内容,而是使用unittest.mock library module(以前是外部包Mock)。最基本的设置适用于wxPython的大多数部分,但我遇到了一种情况,我看不到一个简单的方法(可能是因为我相对不熟悉模拟直到本周)。

目前,我的conf.py文件的结尾具有以下内容:

MOCK_MODULES = ['wx.lib.newevent']  # I've skipped irrelevant entries...

for module_name in MOCK_MODULES:
    sys.modules[module_name] = mock.Mock()

对于所有wxPython模块而不是wx.lib.newevent,这非常有效。但是,这里我使用newevent.NewCommandEvent()函数[1]为特定场景创建事件。在这种情况下,我会在NewCommandEvent()来电时收到警告TypeError: 'Mock' object is not iterable

虽然我可以看到如何使用patching来处理这个问题来构建单元测试(我将在下个月进行测试!),我很难看到如何将其整合到我的Sphinx配置中的一个简单级别。

修改:我刚尝试使用MagicMock();这仍然会在同一点产生错误,尽管它现在产生ValueError: need more than 0 values to unpack。这似乎是朝着正确方向迈出的一步,但我仍然不确定如何处理这个模块的明确设置。也许这是最好的解决方案?


脚注

  1. 是的,这是一个函数,命名约定使它看起来像一个类; wxPython遵循整个wxWidgets工具包中使用的C ++命名约定。

1 个答案:

答案 0 :(得分:2)

从错误中看,它实际上正在执行newevent.NewCommandEvent(),所以我假设您的代码中的某个位置有一个顶级行:

import wx.lib.newevent
...
event, binder = wx.lib.newevent.NewCommandEvent()

当autodoc导入模块时,它会尝试运行这行代码,但由于NewCommandEvent实际上是Mock对象,因此Python无法将其输出绑定到(event, binder)元组。有两种可能的解决方案。第一种是将代码更改为在导入时不执行,也可以将其包装在if __name__ == '__main__'内。我建议使用此解决方案,因为在导入时创建这样的对象通常会产生前期副作用。

第二种解决方案是告诉Mock对象返回适当的值:

wx.lib.newevent.NewCommandEvent = mock.Mock(return_value=(Mock(), Mock()))

但是,如果您在代码中使用返回的值执行任何操作,则可能会遇到同样的问题。