我已经编写了一个用于测试的assert_raised
上下文管理器,它会检查是否引发了预期的异常,如果没有引发AssertionError
。我也写了一个doctest来测试这个,但doctest一直在失败,我不完全确定为什么。这是doctest:
>>> 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)
答案 0 :(得分:4)
Doctests有处理引发异常的特殊代码。因此,它将识别输出何时是异常。为了识别这一点,预期输出必须以单词Traceback
开头。您的预期输出不会以此开头,因此,doctest不会将输出识别为期望异常,因此,它不会期望异常,因此当异常到来时,它将失败。
您可以通过三种方式解决此问题:
摆脱输出的Raising XXXError...
部分。 [懒]
为doctest实现特殊输出过滤器,使doctest无法忽略Raising XXXError...
- 部分[复杂]
停止将doctests用于除测试文档之外的其他内容。 [正确]
上面的代码显然是 not 如何使用此上下文管理器的示例代码,它是测试上下文管理器工作的代码。这样的测试永远不应该是doctests。 Doctests是痛苦且有限的,只应用于测试文档。