2010-10-05 129 views
1

的文档测试以下的(无义)Python模块的失败:Doctests:如何抑制/忽略输出?

""" 
>>> L = [] 
>>> if True: 
... append_to(L) # XXX 
>>> L 
[1] 
""" 

def append_to(L): 
    L.append(1) 
    class A(object): 
     pass 
    return A() 

import doctest; doctest.testmod() 

这是因为线后的输出标记为XXX是<__main__.A object at ...>(其由append_to返回)。当然,我可以把这个输出直接放在标记为XXX的行后面,但在我的情况下,这会使读者分心,使其不能被实际测试,即功能append_to的副作用。所以我怎样才能压制这个输出或者我怎么能忽略它。我试过它:

""" 
>>> L = [] 
>>> if True: 
... append_to(L) # doctest: +ELLIPSIS 
    ... 
>>> L 
[1] 
""" 

def append_to(L): 
    L.append(1) 
    class A(object): 
     pass 
    return A() 

import doctest; doctest.testmod() 

但是,这产生了一个ValueError: line 4 of the docstring for __main__ has inconsistent leading whitespace: ' ...'

我不想做的是将行append_to(L)更改为这样会抑制输出,因为doctest是为了文档的目的,并向读者展示模块应该如何使用。 (在这种情况下被记录在案,append_to应使用语句似与不似函数编写_ = append_to(L)会与此不同的读者。)

回答

3

重写:这其实现在不工作;我意识到我之前编写的“doctest”其实并没有被解析为模块docstring,所以测试没有通过:它只是没有运行。

我一定要仔细检查一下。

__doc__ = """ 
>>> L = [] 
>>> if True: 
... append_to(L) # doctest: +IGNORE_RESULT 
>>> L 
[1] 
""".replace('+IGNORE_RESULT', '+ELLIPSIS\n<...>') 

def append_to(L): 
    L.append(1) 
    class A(object): 
     pass 
    return A() 

我不确定这是否符合更具可读性的条件。请注意,<...>没有什么特别之处:只有当实际返回值具有该形式时才会起作用,就像它在这种情况下一样(即它是<module.A object at 0x...>)。 ELLIPSIS选项使得...“在实际输出”¹中匹配任何子串。所以我不认为有办法让它匹配整个输出。

更新:要做到这一点,“正确”的方式,它看起来像你想打电话doctest.register_optionflag('IGNORE_RESULT'),子类doctest.OptionChecker,并安排该子类的实例由文档测试使用。大概这意味着通过$ python -m doctest your_module.py运行你的doctest不是一个选项。

0

请尽量给完全独立的,可运行的代码;即使您在演示问题时,代码也应该自行运行以重现问题,因此解决方案可以直接复制代码以演示答案。

我不知道这个干净的解决方案,我以前就打过它;它似乎是模糊(更直白:马虎)测试定义doctests提供的副作用。解决方法是记住您可以在doctests中定义函数,因此您可以将整个测试作为单个函数而不是其单独的语句来包含。

def append_to(l): 
    """ 
    >>> L = [] 
    >>> def test(): 
    ...  if True: 
    ...   append_to(L) # XXX 
    >>> test() 
    >>> L 
    [1] 

    >>> def test(): 
    ...  L = [] 
    ...  if True: 
    ...   append_to(L) # XXX 
    ...  return L 
    >>> test() 
    [1] 

    """ 
    l.append(1) 
    return object() 

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

通过提供自包含的可运行代码,你的意思是什么?我给出的代码可以直接用Python解释器运行(正如我提到的那样产生了错误) - 至少在这里使用Python 2.6。 至于你的回答:我也想过把所有东西都包装在一个函数中,这样返回值就是'None',但是完全如你所写,这看起来不是一个很干净的解决方案。 – Marc 2010-10-05 10:02:06

+0

我只是误导了它; doctest被写为一个单独的字符串,而不是被测试的属性 - 我从来不这样做。无论如何,只要你的测试确实解决了一个单一的结果,上述内容相当干净。如果一个测试不适合这种模式,例如。如果你有多个相互关联的语句,测试一些结果值而不是其他的,那么它将不会工作得很好。真的需要有一个doctest.DISCARD标志。 – 2010-10-05 10:10:51