了解在单元测试中捕获 ValueError 的语句 class
Understanding with statement to catch ValueError in unittest class
单元测试的新手和 Python 一般而言,在单元测试介绍教程中遇到示例,其中使用 with 语句捕获 ValueError。
正在测试的脚本(invoice_calculator.py)是:
def divide_pay(amount, staff_hours):
"""
Divide an invoice evenly amongst staff depending on how many hours they
worked on a project
"""
total_hours = 0
for person in staff_hours:
total_hours += staff_hours[person]
if total_hours == 0:
raise ValueError("No hours entered")
per_hour = amount / total_hours
staff_pay = {}
for person in staff_hours:
pay = staff_hours[person] * per_hour
staff_pay[person] = pay
return staff_pay
单元测试包含此函数以捕获边缘情况,其中 staff_hours = None
:
import unittest
from invoice_calculator import divide_pay
class InvoiceCalculatorTests(unittest.TestCase):
def test_equality(self):
pay = divide_pay(300.0, {"Alice": 3.0, "Bob": 6.0, "Carol": 0.0})
self.assertEqual(pay, {'Bob': 75.0, 'Alice': 75.0, 'Carol': 150.0})
def test_zero_hours_total(self):
with self.assertRaises(ValueError):
pay = divide_pay(360.0, {"Alice": 0.0, "Bob": 0.0, "Carol": 0.0})
if __name__ == "__main__":
unittest.main()
关于 test_zero_hours_total(self)
中 with
语句的使用,就此语句 works/is 的执行方式而言,这里实际发生了什么?
test_zero_hours_total()
函数是否基本上按如下方式工作(外行人的描述):预期错误应该是 ValueError
(我们通过将 ValueError
传递给函数 assertRaises()
) 当 360.0, {"Alice": 0.0, "Bob": 0.0, "Carol": 0.0}
(这会在 divide_pay()
中引发 ValueError
)作为参数传递给 divide_pay()
函数时?
我不是 100% 确定你的问题是什么...
TestCase.assertRaises
创建一个可以用作上下文管理器的对象(这就是它可以与 with
语句一起使用的原因)。这样使用时:
with self.assertRaises(SomeExceptionClass):
# code
context manager的__exit__
方法会检查传入的异常信息,如果缺失,会抛出AssertionError
导致测试失败。如果异常类型错误(例如,不是 SomeExceptionClass
的实例),也会抛出 AssertionError
。
听起来你明白测试在做什么。如果 assertRaises
不存在,您可能会发现如何编写测试很有用。
def test_zero_hours_total(self):
try:
pay = divide_pay(360.0, {"Alice": 0.0, "Bob": 0.0, "Carol": 0.0})
except ValueError:
# The exception was raised as expected
pass
else:
# If we get here, then the ValueError was not raised
# raise an exception so that the test fails
raise AssertionError("ValueError was not raised")
请注意,您不必使用 assertRaises
作为上下文管理器。您还可以将异常、可调用对象和该可调用对象的参数传递给它:
def test_zero_hours_total(self):
self.assertRaises(ValueError, divide_pay, 360.0, {"Alice": 0.0, "Bob": 0.0, "Carol": 0.0})
单元测试的新手和 Python 一般而言,在单元测试介绍教程中遇到示例,其中使用 with 语句捕获 ValueError。
正在测试的脚本(invoice_calculator.py)是:
def divide_pay(amount, staff_hours):
"""
Divide an invoice evenly amongst staff depending on how many hours they
worked on a project
"""
total_hours = 0
for person in staff_hours:
total_hours += staff_hours[person]
if total_hours == 0:
raise ValueError("No hours entered")
per_hour = amount / total_hours
staff_pay = {}
for person in staff_hours:
pay = staff_hours[person] * per_hour
staff_pay[person] = pay
return staff_pay
单元测试包含此函数以捕获边缘情况,其中 staff_hours = None
:
import unittest
from invoice_calculator import divide_pay
class InvoiceCalculatorTests(unittest.TestCase):
def test_equality(self):
pay = divide_pay(300.0, {"Alice": 3.0, "Bob": 6.0, "Carol": 0.0})
self.assertEqual(pay, {'Bob': 75.0, 'Alice': 75.0, 'Carol': 150.0})
def test_zero_hours_total(self):
with self.assertRaises(ValueError):
pay = divide_pay(360.0, {"Alice": 0.0, "Bob": 0.0, "Carol": 0.0})
if __name__ == "__main__":
unittest.main()
关于 test_zero_hours_total(self)
中 with
语句的使用,就此语句 works/is 的执行方式而言,这里实际发生了什么?
test_zero_hours_total()
函数是否基本上按如下方式工作(外行人的描述):预期错误应该是 ValueError
(我们通过将 ValueError
传递给函数 assertRaises()
) 当 360.0, {"Alice": 0.0, "Bob": 0.0, "Carol": 0.0}
(这会在 divide_pay()
中引发 ValueError
)作为参数传递给 divide_pay()
函数时?
我不是 100% 确定你的问题是什么...
TestCase.assertRaises
创建一个可以用作上下文管理器的对象(这就是它可以与 with
语句一起使用的原因)。这样使用时:
with self.assertRaises(SomeExceptionClass):
# code
context manager的__exit__
方法会检查传入的异常信息,如果缺失,会抛出AssertionError
导致测试失败。如果异常类型错误(例如,不是 SomeExceptionClass
的实例),也会抛出 AssertionError
。
听起来你明白测试在做什么。如果 assertRaises
不存在,您可能会发现如何编写测试很有用。
def test_zero_hours_total(self):
try:
pay = divide_pay(360.0, {"Alice": 0.0, "Bob": 0.0, "Carol": 0.0})
except ValueError:
# The exception was raised as expected
pass
else:
# If we get here, then the ValueError was not raised
# raise an exception so that the test fails
raise AssertionError("ValueError was not raised")
请注意,您不必使用 assertRaises
作为上下文管理器。您还可以将异常、可调用对象和该可调用对象的参数传递给它:
def test_zero_hours_total(self):
self.assertRaises(ValueError, divide_pay, 360.0, {"Alice": 0.0, "Bob": 0.0, "Carol": 0.0})