gpt4 book ai didi

python - 使用 assertRaises - 处理传播的异常

转载 作者:太空宇宙 更新时间:2023-11-04 06:25:03 25 4
gpt4 key购买 nike

我有一些代码,我正在测试一个包装异常,当它失败并且异常传播时,我认为错误消息和回溯不够详细,主要是因为它没有告诉我预期与. 测试,我想要异常和期望的详细信息。

我调整了我的测试(参见下面的示例代码)。我想知道这种方法是否有效,是否有任何 Python 测试或模拟框架允许直接实现它? (目前我正在使用 unittest 和 mox)

this question 的答案之一简要介绍了在这种情况下使用 self.fail 的适当性,但并未详细说明。我的假设是,如果我尝试将测试限制在一个区域,我可以通过测试。

注意:如果您运行该代码示例,它应该会失败,以演示我希望看到的行为。我正在使用 Python 2.7、Mox 0.5.3

import sys
import urllib2
from contextlib import closing

try:
import lxml.etree as ET
except ImportError:
import xml.etree.ElementTree as ET


class Defect(Exception):
"""Wrapped exception, for module error detection"""
def __init__(self, *args):
Exception.__init__(self, *args)
self.wrapped_exc = sys.exc_info()


class StudioResources:
"""Dummy class"""
def _opener(self, request, html=False):
with closing(urllib2.urlopen(request)) as response:
try:
if html:
import lxml.html
return lxml.html.parse(response)
else:
return ET.parse(response)
except urllib2.HTTPError, e:
if e.code in [400, 500]: # Bad Request, Internal Server Error
raise Defect, "report error to the library maintainer"
else:
raise


###
# Tests
###
import unittest
import mox
import traceback
import difflib
import urllib
import httplib


def format_expectation(exc_expected=None, exc_instance=None):
"""Synopsis - For exceptions, inspired by _AssertRaisesContext

try:
self.assertRaises(myexc, self.studio._opener, None)
except Exception, e:
self.fail(format_expectation(exc_expected=myexc, exc_instance=e))
"""
if not isinstance(exc_expected, type) or exc_instance is None:
raise ValueError, "check __init__ args"

differ = difflib.Differ()
inst_class = exc_instance.__class__
def fullname(c): return "%s.%s" % (c.__module__, c.__name__)
diff = differ.compare(
(fullname(inst_class),), (fullname(exc_expected),))
_str = ("Unexpected Exception type. unexpected:- expected:+\n%s"
% ("\n".join(diff),))
return _str


class StudioTest(mox.MoxTestBase):
def setUp(self):
mox.MoxTestBase.setUp(self)
self.studio = StudioResources()

def test_opener_defect(self):
f = urllib.addinfourl(urllib2.StringIO('dummy'), None, None)
RESP_CODE = 501
self.mox.StubOutWithMock(f, 'read')
self.mox.StubOutWithMock(urllib2, 'urlopen')
urllib2.urlopen(mox.IgnoreArg()).AndReturn(f)
f.read(mox.IgnoreArg()).AndRaise(urllib2.HTTPError(
'http://c.com', RESP_CODE, httplib.responses[RESP_CODE], "", None))
self.mox.ReplayAll()
try:
with self.assertRaises(Defect) as exc_info:
self.studio._opener(None)
except Exception, e:
traceback.print_exc()
self.fail(format_expectation(exc_expected=Defect, exc_instance=e))
# check the response code
exc, inst, tb = exc_info.exception.wrapped_exc
self.assertEquals(inst.code, RESP_CODE)
self.mox.VerifyAll()


if __name__ == '__main__':
unittest.main()

最佳答案

在编写单元测试时,将测试限制在一件事上总是一个好主意。我没有发现您的代码有任何问题,但我会将所有内容包装在上下文管理器中。我使用 nose 而不是 unittest,它将任何 AssertionError 视为失败(这意味着无需调用 self.fail()),并且我编写了自己的上下文管理器来处理此问题案件。如果您有兴趣,这是代码:

class assert_raises:

def __init__(self, exception):
self.exception = exception

def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
assert exc_type is self.exception, "Got '{}', expected '{}'"\
.format('None' if exc_type is None else exc_type.__name__,
self.exception.__name__)
return True

然后在这些示例中使用它:

>>> with assert_raised(ValueError):
... raise ValueError

>>> with assert_raised(ValueError):
... pass
Traceback (most recent call last):
...
AssertionError: Got 'None', expected 'ValueError'

>>> with assert_raised(ValueError):
... raise TypeError
Traceback (most recent call last):
...
AssertionError: Got 'TypeError', expected 'ValueError'

由于引发了 AssertionError,nose 将其视为失败并打印完整的回溯。这是为 nose 设计的,但是为 unittest 和 mox 调整它是一件微不足道的事情。如果您不太关心失败的确切模式,您甚至可以按原样使用它。

关于python - 使用 assertRaises - 处理传播的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8954008/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com