17

Python 文档测试很酷。让我从一个简单的例子开始:

def foo():
  """
  >>> foo()
  hello world
  """
  print "hello world"

现在让我们假设某些部分有些变化,例如,因为它是时间值或随机数。通常,文档测试允许我使用 +ELLIPSIS 选项指定通配符。

例如,当“world”是一个变化的字符串时,这很好用:

def foo():
  """
  >>> foo()   # doctest: +ELLIPSIS
  hello ...
  """
  print "hello world"

然而,就我而言,变量字符串位于行首:

def foo():
  """
  >>> foo() # doctest: +ELLIPSIS
  ... world
  """
  print "hello world"

这很糟糕,因为开头的 3 个点被解释为行继续字符,而不是输出的省略号。因此,此测试失败:

Failed example:
    foo() # doctest: +ELLIPSIS
    world
Expected nothing
Got:
    hello world

所以,我现在可以重写我的可能,将可变部分放在其他地方,但是有没有办法教 doctest 一行开头的 3 个点是省略号?

4

5 回答 5

9

这是一个快速而肮脏的黑客攻击:

def foo():
    """
    >>> foo() # doctest: +ELLIPSIS
    [...] world
    """
    print "hello world"

if __name__ == "__main__":
    import doctest

    OC = doctest.OutputChecker
    class AEOutputChecker(OC):
        def check_output(self, want, got, optionflags):
            from re import sub
            if optionflags & doctest.ELLIPSIS:
                want = sub(r'\[\.\.\.\]', '...', want)
            return OC.check_output(self, want, got, optionflags)

    doctest.OutputChecker = AEOutputChecker
    doctest.testmod()

这仍然理解正常的 ( ... ) 省略号,但它添加了一个新的 ( [...] ) 不会引起行开始歧义。

doctest 很难猜测是否存在待处理的行继续或者是否是行开始省略号 - 从理论上讲,如果您将 DocTestParser 子类化来完成这项工作,但它可能不会很有趣。

在复杂的情况下,您可能应该推出自己的 DocTestRunner,它会使用新的 OutputChecker 并使用它而不是普通的 testmod,但这应该在简单的情况下进行。

于 2011-04-28T15:20:26.597 回答
7

您可以ELLIPSIS_MARKER为您的测试更新,以免...与行延续点混淆:

def foo():
    """
    >>> import doctest
    >>> doctest.ELLIPSIS_MARKER = '-ignore-'
    >>> foo()
    hello world
    >>> foo() # doctest: +ELLIPSIS
    -ignore- world
    """
    print "hello world"

if __name__ == "__main__":
    import doctest
    doctest.testmod()


免责声明:上面的示例在 doctest 运行时有效

$ py.test --doctest-module foo.py

或者

$ python foo.py

但是,由于我不明白的原因,它在运行 doctests 时不起作用

$ python -m doctest foo.py
于 2017-02-20T08:13:45.563 回答
4

这是一种更简单的方法:只需在以未知输出开头的行之前打印一个虚拟字符串。

像这样:

def foo():
  """
  >>> print 'ignore'; foo() # doctest: +ELLIPSIS
  ignore... world
  """
  print "hello world"
于 2014-06-19T05:19:12.697 回答
2

我最终得到了这个解决方法。

def foo():
    """
    >>> foo()  # doctest: +NORMALIZE_WHITESPACE, +ELLIPSIS
    <BLANKLINE>
    ... world
    """
    print("hello world")

它至少可以在没有非空白字符或其他解决方法的情况下工作。

于 2020-01-29T10:56:42.340 回答
0

如果您只是删除省略号后的尾随空格,这应该可以。

def foo():   
    """
    >>> foo()  # doctest: +ELLIPSIS   
    ...world
    """
    print "hello world"
于 2021-02-05T13:41:44.237 回答