在Python中测试函数是否抛出异常
unittest单元测试框架用于验证代码是否按设计执行。为了实现这一点,unittest 以面向对象的方式支持一些重要的方法:
- 测试夹具
- 测试用例
- 测试套件
- 测试赛跑者
可以从 https://www.geeksforgeeks.org/unit-testing-python-unittest/ 获得对上述术语的更深入了解
assertRaises() – 它允许封装异常,这意味着测试可以在不退出执行的情况下抛出异常,就像未处理异常的情况一样。如果引发异常,则测试通过,如果引发另一个异常则给出错误,如果没有引发异常,则测试失败。
有两种方法可以使用 assertRaises:
- 使用关键字参数。
assertRaises(exception, function, *args, **keywords)
只需将异常、可调用函数和可调用函数的参数作为将引发异常的关键字参数传递。
- 使用上下文管理器
assertRaises(exception)
进行一个函数调用,该函数调用应在上下文中引发异常。上下文管理器将捕获异常并将其存储在对象的异常属性中。当我们必须对引发的异常进行额外检查时,这很有用。
如果函数没有引发异常,或者assert 语句引发的异常与预期的异常不同,我们编写一个单元测试失败。因此,通过这种方法,我们可以检查函数是否引发了异常。
示例 1:
Python3
import unittest
class MyTestCase(unittest.TestCase):
# Returns true if 1 + '1' raises a TypeError
def test_1(self):
with self.assertRaises(Exception):
1 + '1'
if __name__ == '__main__':
unittest.main()
Python3
import unittest
class MyTestCase(unittest.TestCase):
# Returns false if 1 + 1 raises no Exception
def test_1(self):
with self.assertRaises(Exception):
1 + 1
if __name__ == '__main__':
unittest.main()
Python3
import unittest
class MyTestCase(unittest.TestCase):
# Returns true if 100 / 0 raises an Exception
def test_1(self):
with self.assertRaises(ZeroDivisionError):
100 / 0
if __name__ == '__main__':
unittest.main()
Python3
import unittest
class MyTestCase(unittest.TestCase):
# Returns true if GeeksforGeeks.txt file is not present and raises an EnvironmentError
# Exception
# In this example expected exception is RuntimeError while generated exception is
# EnvironmentError, thus returns false
def test_1(self):
with self.assertRaises(RuntimeError):
file = open("GeeksforGeeks.txt", 'r')
if __name__ == '__main__':
unittest.main()
输出 :
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
在这里,在输出中的“。”在输出的第一行表示测试已通过并且函数在添加整数值和字符串值时抛出了TypeError异常。
示例 2:
Python3
import unittest
class MyTestCase(unittest.TestCase):
# Returns false if 1 + 1 raises no Exception
def test_1(self):
with self.assertRaises(Exception):
1 + 1
if __name__ == '__main__':
unittest.main()
输出 :
F
======================================================================
FAIL: test_1 (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/5bc65171e57a3294596f5333f4b7ed53.py", line 6, in test_1
1 + 1
AssertionError: Exception not raised
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)
由于将整数添加到整数(在本例中为 1 + 1)不会引发任何异常,因此导致单元测试失败。
示例 3:
Python3
import unittest
class MyTestCase(unittest.TestCase):
# Returns true if 100 / 0 raises an Exception
def test_1(self):
with self.assertRaises(ZeroDivisionError):
100 / 0
if __name__ == '__main__':
unittest.main()
输出 :
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
任何数字除以 0 都会给出ZeroDivisionError异常。因此,在示例 3 中,当 100 除以 0 时,它会引发 ZeroDivisionError 类型的异常,从而导致单元测试通过。因此 ”。”在输出中表示测试已通过。
示例 4:
Python3
import unittest
class MyTestCase(unittest.TestCase):
# Returns true if GeeksforGeeks.txt file is not present and raises an EnvironmentError
# Exception
# In this example expected exception is RuntimeError while generated exception is
# EnvironmentError, thus returns false
def test_1(self):
with self.assertRaises(RuntimeError):
file = open("GeeksforGeeks.txt", 'r')
if __name__ == '__main__':
unittest.main()
输出 :
E
======================================================================
ERROR: test_1 (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/8520c06939bb0023b4f76f381b2c8cf2.py", line 11, in test_1
file = open("GeeksforGeeks.txt", 'r')
FileNotFoundError: [Errno 2] No such file or directory: 'GeeksforGeeks.txt'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
当我们尝试打开一个不存在的文件时,它会引发一个IOError ,它是EnvironmentError的子类。在上面的示例中,单元测试失败是因为函数引发的异常类型应该是RuntimeError类型,而不是引发了EnvironmentError异常。由于引发的异常和预期的异常不同,因此会产生错误。