2012-02-02 73 views
1

我有一點麻煩doctest和協程...蟒蛇文檔測試與協程

def coroutine(func): 
    def start(*args, **kwargs): 
     cr=func(*args, **kwargs) 
     cr.next() 
     return cr 
    start.__name__=func.__name__ 
    return start 

@coroutine 
def leader_tracking(): 
    """ 
    Tracks 'leader' status - only returns transitions 

    >>> lt=leader_tracking() 
    >>> print lt.send(False) 

    >>> print lt.send(False) 

    """ 
    last_status=False 
    result=("nop", None) 

    while True: 
     status=(yield result) 

     if status!=last_status: 
      direction="up" if last_status==False else "down" 
      last_status=status 
      result=("tr", direction) 
     else: 
      result=("nop", None) 

如果我使用通常的文檔測試腳手架:

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

doctest沒有顯示任何東西,而如果我使用更蠻力的方法:

lt=leader_tracking() 
print lt.send(True) 
print lt.send(False) 
print lt.send(False) 
print lt.send(True) 
print lt.send(True) 
print lt.send(True) 
print lt.send(True) 
print lt.send(False) 

我可以看到預期的結果:

('tr', 'up') 
('tr', 'down') 
('nop', None) 
('tr', 'up') 
('nop', None) 
('nop', None) 
('nop', None) 
('tr', 'down') 

我在做什麼毛病doctest

回答

6

的文檔測試模塊着眼於它們被存儲在一個函數的__doc__屬性文檔字符串。你的協同裝飾只複製__name__,所以docstring會丟失,doctest找不到它。你可以手動指定__doc__屬性,但更好的方法是使用functools模塊:的func

import functools 

def coroutine(func): 
    @functools.wraps(func) 
    def start(*args, **kwargs): 
     cr = func(*args, **kwargs) 
     cr.next() 
     return cr 
    return start 

functools.wraps裝飾拷貝所有的各種元數據屬性到包裝功能部件start,包括文檔字符串,這樣的doctest將按預期工作。

另外請注意,您的文檔測試意見應包括預期的輸出,以正常工作:

@coroutine 
def leader_tracking(): 
    """ 
    Tracks 'leader' status - only returns transitions 

    >>> lt=leader_tracking() 
    >>> print lt.send(True) 
    ('tr', 'up') 
    >>> print lt.send(False) 
    ('tr', 'down') 
    >>> print lt.send(False) 
    ('nop', None) 
    """ 
    last_status = False 
    result = ("nop", None) 

    while True: 
     status = yield result 

     if status != last_status: 
      direction = "up" if last_status == False else "down" 
      last_status = status 
      result = ("tr", direction) 
     else: 
      result = ("nop", None) 
+0

+1:了不起! – jldupont 2012-02-02 11:42:21