【问题标题】:Why is doctest skipping tests on imported methods?为什么 doctest 跳过对导入方法的测试?
【发布时间】:2021-04-11 18:39:15
【问题描述】:

我有一个 python 模块 some_module 和一个 __init__.py 导入方法的文件,如下所示:

from .some_python_file import some_method

some_method 有一个包含文档测试的文档字符串:

def some_method():
    """
    >>> assert False
    """

但是当我在模块上运行doctest 时,即使测试失败,它也会通过。

import some_module
# How do I get this to consistently fail, regardless of whether
# `some_module.some_method` was declared inline or imported?
assert doctest.testmod(some_module).failed == 0

如果我改为在 __init__.py 文件中定义 some_method,则 doctest 正确失败。

为什么这两种情况的表现不同?该方法存在并且在两种情况下都具有相同的__doc__ 属性。

如何让 doctest 运行在导入模块的方法的 dostrings 中定义的测试?

【问题讨论】:

    标签: python-3.x doctest


    【解决方案1】:

    在 Python 中,模块由单个文件定义,在您的情况下,some_python_file 是一个模块,而 __init__ 是另一个模块。 Doctest 有一项检查,仅针对可从模块访问的示例运行测试,该模块可在 here 找到。

    在实践中查看此行为的最佳方法是在调用 doctest.testmod(some_module) 之前使用 PDBpdb.set_trace() 并按照逻辑进入。

    乐: Doctest 根据this comment 忽略导入的方法。如果您希望能够运行您的测试,您可能应该在您的模块中定义一个主函数并使用python some_module.py 运行测试测试。你可以关注this example

    要实现您的预​​期行为,您需要在您的 init 文件中手动创建 __test__ dict:

    from .some_python_file import some_method
    
    __test__ = {"some_method": some_method}
    

    也请参阅this link

    【讨论】:

    • 这是有用的信息,但它仍然不能解释为什么如果我从另一个模块导入一个方法,该方法的文档字符串不被认为是导入模块的一部分。它也没有解决后续问题,即如何在不了解内部实现细节(如方法是内联定义还是导入)的情况下从导入模块开始实际运行 doctest。
    • 嘿@CraigGidney 我用更多信息更新了我的答案,你的问题有一个解决方法。
    【解决方案2】:

    不搜索导入到模块中的对象。

    请参阅which docstrings are examined 上的文档。

    您可以将导入的函数注入到模块的__test__ 属性中以测试导入的对象:

    __test__ = {'some_method': some_method}
    

    【讨论】:

    • 啊,这很好地解释了这种行为。有没有办法解决这个限制?我想要搜索导入的文档字符串的行为。
    • 看起来我可以为每个导入的对象定义__test__ = {name1: obj1, name2: obj2, ...} 并且有效?
    • @CraigGidney 是的,我打算补充一下(现在已经做了)。这告诉 doctest 显式测试 dict 中枚举对象中的文档字符串。
    【解决方案3】:

    我偶然发现了这个问题,因为我正在破解导入对象的 __doc__ 属性。

    from foo import bar
    bar.__doc__ = """
    >>> assert True
    """
    
    and I was also wondering why the doctest of bar did not get executed by the doctest runner.
    
    The previously given answer to add a `__test__` mapping solved it for good.
    
    ```python
    __test__ = dict(bar=bar.__doc__)
    

    我认为对这种行为的解释如下。如果您使用的是库,比如说 NumPy,您不希望收集它们的所有文档测试并在您自己的代码中运行。 很简单,因为它是多余的。 您应该相信库的开发人员会(持续地)测试他们的代码,所以您不必这样做。

    如果您在自己的代码中定义了测试,则应该有一个测试收集器(例如 pytest)进入项目结构的所有文件并运行这些文件。 您最终会在使用过的库中测试所有 doctest,这需要花费大量时间。所以忽略导入的文档测试的决定是非常明智的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-01
      • 2014-03-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-30
      • 1970-01-01
      相关资源
      最近更新 更多