2012-04-10 83 views
4

我已經編寫了一個assert_raised上下文管理器,用於測試哪些檢查如預期的異常被引發,並且如果不引發AssertionError。我也寫了一個文檔測試來測試這個,但文檔測試仍然失敗,我不完全確定爲什麼。這裏是文檔測試:文檔測試中的鏈接異常

>>> for e in [TypeError, ValueError, KeyError]: 
...  with assert_raised(TypeError, ValueError): 
...   print('Raising {}...'.format(e.__name__)) 
...   raise e 
Raising TypeError... 
Raising ValueError... 
Raising KeyError... 
Traceback (most recent call last): 
    ... 
AssertionError: Got 'KeyError', expected 'TypeError, ValueError' 

和實際發生異常時:

Traceback (most recent call last): 
    File "<doctest dtlibs.mock.assert_raised[3]>", line 4, in <module> 
    raise e 
KeyError 

During handling of the above exception, another exception occurred: 

Traceback (most recent call last): 
    File "C:\Python32\lib\doctest.py", line 1253, in __run 
    compileflags, 1), test.globs) 
    File "<doctest dtlibs.mock.assert_raised[3]>", line 4, in <module> 
    raise e 
    File "G:\Projects\Programming\dt-tools\dtlibs\dtlibs\mock.py", line 274, in __exit__ 
    raise self._exception(exc_type.__name__) 
AssertionError: Got 'KeyError', expected 'TypeError, ValueError' 

我不認爲執行是重要的,但在這裏它是萬一我做錯了有(沒有doctest):

class assert_raised: 

    def __init__(self, *exceptions): 
     self.exceptions = exceptions 

    def __enter__(self): 
     return self 

    def __exit__(self, exc_type, exc_val, exc_tb): 
     if exc_type is None: 
      raise self._exception('None') 
     elif self.exceptions and exc_type not in self.exceptions: 
      raise self._exception(exc_type.__name__) 
     return True 

    def _exception(self, got): 
     if len(self.exceptions) == 0: 
      expected = 'an exception' 
     else: 
      expected = ', '.join(e.__name__ for e in self.exceptions) 
     msg = "Got '{}', expected '{}'".format(got, expected) 
     return AssertionError(msg) 

回答

4

Doctests有特殊的代碼來處理異常。因此,它會識別何時輸出異常。爲了認識到這一點,預期的輸出必須以字Traceback開始。您的預期輸出不會以此開始,因此,doctest將無法將輸出識別爲期望發生異常,因此它不會期望發生異常,因此當發生異常時,它將會失敗。

您可以通過三種方式解決這個問題:

  1. 擺脫輸出的Raising XXXError...部分。 [懶]

  2. 實現特殊的輸出過濾器文檔測試其使得文檔測試忽略Raising XXXError... -part [複雜]

  3. 停止使用的doctests其他東西不是測試文檔。 [正確]

上面的代碼顯然是如何使用這個上下文管理示例代碼,它的代碼,測試的上下文管理工作。這樣的測試絕不應該是文檔測試。 Doctests是痛苦和有限的,應該只用於測試文檔。

+1

感謝您的答案,這解釋了它!也許我的文檔有點麻煩,但這實際上只是示例代碼。我也有單元測試套件來測試所有這些。瞭解原因,我只是簡化我的例子。 – aquavitae 2012-04-10 08:15:46