• 14.3 在单元测试中测试异常情况
    • 问题
    • 解决方案
    • 讨论

    14.3 在单元测试中测试异常情况

    问题

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

    解决方案

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

    1. import unittest
    2.  
    3. # A simple function to illustrate
    4. def parse_int(s):
    5. return int(s)
    6.  
    7. class TestConversion(unittest.TestCase):
    8. def test_bad_int(self):
    9. self.assertRaises(ValueError, parse_int, 'N/A')

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

    1. import errno
    2.  
    3. class TestIO(unittest.TestCase):
    4. def test_file_not_found(self):
    5. try:
    6. f = open('/file/not/found')
    7. except IOError as e:
    8. self.assertEqual(e.errno, errno.ENOENT)
    9.  
    10. else:
    11. self.fail('IOError not raised')

    讨论

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

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

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

    1. class TestConversion(unittest.TestCase):
    2. def test_bad_int(self):
    3. try:
    4. r = parse_int('N/A')
    5. except ValueError as e:
    6. self.assertEqual(type(e), ValueError)
    7. else:
    8. self.fail('ValueError not raised')

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

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

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

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

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

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

    原文:

    http://python3-cookbook.readthedocs.io/zh_CN/latest/c14/p03_testing_for_exceptional_conditions_in_unit_tests.html