我可以在Python doctest的行尾添加省略号吗?

Bjo*_*rnD 15 python doctest

Python doctests很酷.让我从一个简单的例子开始:

def foo():
  """
  >>> foo()
  hello world
  """
  print "hello world"
Run Code Online (Sandbox Code Playgroud)

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

当例如"world"是变化的字符串时,这很好用:

def foo():
  """
  >>> foo()   # doctest: +ELLIPSIS
  hello ...
  """
  print "hello world"
Run Code Online (Sandbox Code Playgroud)

但是,在我的情况下,变量字符串位于行的开头:

def foo():
  """
  >>> foo() # doctest: +ELLIPSIS
  ... world
  """
  print "hello world"
Run Code Online (Sandbox Code Playgroud)

这是不好的,因为开头的3个点被解释为行连续字符而不是输出的省略号.因此,此测试失败:

Failed example:
    foo() # doctest: +ELLIPSIS
    world
Expected nothing
Got:
    hello world
Run Code Online (Sandbox Code Playgroud)

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

小智 10

这是一个快速而又脏的黑客:

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()
Run Code Online (Sandbox Code Playgroud)

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

对于doctest来说,猜测是否有一个行继续处理或者它是否是一行开始省略号是非常困难的 - 理论上,如果你继承DocTestParser来完成这项工作,它可以完成,但它可能不会很有趣.

在复杂的情况下,您应该推出自己的DocTestRunner,它将使用新的OutputChecker并使用它而不是普通的testmod,但这应该在简单的场景中完成.


Ped*_*rte 6

您可以更新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()
Run Code Online (Sandbox Code Playgroud)


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

$ py.test --doctest-module foo.py
Run Code Online (Sandbox Code Playgroud)

要么

$ python foo.py
Run Code Online (Sandbox Code Playgroud)

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

$ python -m doctest foo.py
Run Code Online (Sandbox Code Playgroud)


ash*_*bar 5

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

像这样:

def foo():
  """
  >>> print 'ignore'; foo() # doctest: +ELLIPSIS
  ignore... world
  """
  print "hello world"
Run Code Online (Sandbox Code Playgroud)