在 Python assertRaises 中使用上下文管理器 [英] Using a context manager with Python assertRaises

查看:29
本文介绍了在 Python assertRaises 中使用上下文管理器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

unittest 的 Python 文档暗示 assertRaises() 方法可以用作上下文管理器.下面的代码给出了 Python 文档中单元测试的一个简单示例.testsample() 方法中的 assertRaises() 调用工作正常.

The Python documentation for unittest implies that the assertRaises() method can be used as a context manager. The code below shows gives a simple example of the unittest from the Python docs. The assertRaises() call in the testsample() method works fine.

现在我想在异常发生时访问它,但是如果我将其注释掉并取消注释下一个我尝试使用上下文管理器的块,我会得到一个 AttributeError: __exit__ 当我尝试执行代码时.Python 2.7.2 和 3.2.2 都会发生这种情况.我可以在 try...except 块中捕获异常并以这种方式访问​​它,但是 unittest 的文档似乎暗示上下文管理器也会这样做.

Now I'd like to access the exception in when it is raised, but if I comment it out and instead uncomment the next block in which I attempt to used a context manager I get an AttributeError: __exit__ when I attempt to execute the code. This happens for both Python 2.7.2 and 3.2.2. I could catch the exception in a try...except block and access it that way but the documentation for unittest seems to imply the context manager would do this as well.

我还有什么地方做错了吗?

Is there something else I'm doing wrong here?

class TestSequenceFunctions(unittest.TestCase):

    def setUp(self):
        self.seq = [x for x in range(10)]

    def testshuffle(self):
        # make sure the shuffled sequence does not lose any elements
        random.shuffle(self.seq)
        self.seq.sort()
        self.assertEqual(self.seq, [x for x in range(10)])

    def testchoice(self):
        element = random.choice(self.seq)
        self.assert_(element in self.seq)

    def testsample(self):
        self.assertRaises(ValueError, random.sample, self.seq, 20)

        # with self.assertRaises(ValueError, random.sample, self.seq, 20):
        #     print("Inside cm")

        for element in random.sample(self.seq, 5):
            self.assert_(element in self.seq)

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

推荐答案

单元测试的源代码 没有显示assertRaises 的异常钩子:

The source code for unittest doesn't show an exception hook for assertRaises:

class _AssertRaisesContext(object):
    """A context manager used to implement TestCase.assertRaises* methods."""

    def __init__(self, expected, test_case, expected_regexp=None):
        self.expected = expected
        self.failureException = test_case.failureException
        self.expected_regexp = expected_regexp

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, tb):
        if exc_type is None:
            try:
                exc_name = self.expected.__name__
            except AttributeError:
                exc_name = str(self.expected)
            raise self.failureException(
                "{0} not raised".format(exc_name))
        if not issubclass(exc_type, self.expected):
            # let unexpected exceptions pass through
            return False
        self.exception = exc_value # store for later retrieval
        if self.expected_regexp is None:
            return True

        expected_regexp = self.expected_regexp
        if isinstance(expected_regexp, basestring):
            expected_regexp = re.compile(expected_regexp)
        if not expected_regexp.search(str(exc_value)):
            raise self.failureException('"%s" does not match "%s"' %
                     (expected_regexp.pattern, str(exc_value)))
        return True

因此,如您所料,如果您想拦截异常同时仍保持 assertRaises 测试,那么形成自己的 try/except 块是一种可行的方法:

So, as you suspected, forming your own try/except block is the way to go if you want to intercept the exception while still keeping the assertRaises test:

def testsample(self):
    with self.assertRaises(ValueError):
         try:
             random.sample(self.seq, 20)
         except ValueError as e:
             # do some action with e
             self.assertEqual(e.args,
                              ('sample larger than population',))
             # now let the context manager do its work
             raise                    

这篇关于在 Python assertRaises 中使用上下文管理器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆