2012-04-10 86 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