14.3 在�元测试中测试异常情况¶

问题¶

你想写个测试用例�准确的判断�个异常是�被抛出。

解决方案¶

对于异常的测试�使用 assertRaises() 方法。 例如,如果你想测试�个函数抛出了 ValueError 异常,�下�这样写:

import unittest

# A simple function to illustrate
def parse_int(s):
    return int(s)

class TestConversion(unittest.TestCase):
    def test_bad_int(self):
        self.assertRaises(ValueError, parse_int, 'N/A')

如果你想测试异常的具体值,需�用到�外一�方法:

import errno

class TestIO(unittest.TestCase):
    def test_file_not_found(self):
        try:
            f = open('/file/not/found')
        except IOError as e:
            self.assertEqual(e.errno, errno.ENOENT)

        else:
            self.fail('IOError not raised')

讨论¶

assertRaises() 方法为测试异常存在性�供了一个简便方法。 一个常�的陷阱是手动去进行异常检测。比如:

class TestConversion(unittest.TestCase):
    def test_bad_int(self):
        try:
            r = parse_int('N/A')
        except ValueError as e:
            self.assertEqual(type(e), ValueError)

这�方法的问题在于它很容易��其他情况,比如没有任何异常抛出的时候。 那么你还得需�增加�外的检测过程,如下�这样:

class TestConversion(unittest.TestCase):
    def test_bad_int(self):
        try:
            r = parse_int('N/A')
        except ValueError as e:
            self.assertEqual(type(e), ValueError)
        else:
            self.fail('ValueError not raised')

assertRaises() 方法会处�所有细节,因此你应该使用它。

assertRaises() 的一个缺点是它测�了异常具体的值是多少。 为了测试异常值,�以使用 assertRaisesRegex() 方法, 它��时测试异常的存在以�通过正则�匹�异常的字符串表示。例如:

class TestConversion(unittest.TestCase):
    def test_bad_int(self):
        self.assertRaisesRegex(ValueError, 'invalid literal .*',
                                       parse_int, 'N/A')

assertRaises() 和 assertRaisesRegex() 还有一个容易忽略的地方就是它们还能被当�上下文管�器使用:

class TestConversion(unittest.TestCase):
    def test_bad_int(self):
        with self.assertRaisesRegex(ValueError, 'invalid literal .*'):
            r = parse_int('N/A')

但你的测试涉�到多个执行步骤的时候这�方法就很有用了。