2010-10-05 68 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