unittest未捕获calculate_factorial抛出的ValueError异常问题
问题原因
- 你的
test_factorial测试用例没有声明预期ValueError异常:unittest的默认规则是,测试用例执行过程中抛出的所有未被显式捕获的异常都会被判定为用例执行错误。你当前直接调用calculate_factorial(n),当输入为负数时异常直接透传,没有被unittest的异常校验逻辑识别为预期行为,因此报错。 - 测试逻辑和用户输入强耦合的写法不符合单元测试规范:标准单元测试应该预设固定测试用例,分别覆盖合法整数、负数、非整数输入等不同场景,而不是依赖用户动态输入的
n值决定测试逻辑。
修复方案
适配现有输入逻辑的临时修改
如果要保留你当前用户动态输入参数的逻辑,只需要修改test_factorial方法,针对不同输入值走对应的校验逻辑即可:
def test_factorial(self): print('Function is starting to check for values') print() if n < 0: # 用assertRaises捕获预期的ValueError,同时校验异常信息 with self.assertRaises(ValueError) as ctx: calculate_factorial(n) self.assertEqual(str(ctx.exception), 'number should be greater than 0') print('负数校验通过,成功捕获预期ValueError') elif not isinstance(n, int): with self.assertRaises(TypeError) as ctx: calculate_factorial(n) self.assertEqual(str(ctx.exception), 'number should be an integer type') print('非整数类型校验通过,成功捕获预期TypeError') else: result = calculate_factorial(n) print('results are:',result) print() self.assertEqual(result,math.factorial(n)) print('正整数阶乘计算结果校验通过')
标准单元测试写法(推荐)
建议去掉动态输入逻辑,预设固定用例覆盖所有场景,测试结果更稳定可复现,完整代码如下:
from functools import reduce import math import unittest def calculate_factorial(number): if number < 0: raise ValueError('number should be greater than 0') elif type(number) != int: raise TypeError('number should be an integer type') else: data = [] for i in range(number): data.append(number - i) results = reduce((lambda x, y: x * y), data, 1) return results class TestCalc(unittest.TestCase): # 测试正整数阶乘计算结果正确性 def test_positive_factorial_result(self): test_cases = [(0, 1), (1, 1), (5, 120), (7, 5040)] for input_val, expect_val in test_cases: self.assertEqual(calculate_factorial(input_val), expect_val) # 测试负数输入抛出预期异常 def test_negative_input_raise_error(self): with self.assertRaises(ValueError) as ctx: calculate_factorial(-1) self.assertEqual(str(ctx.exception), 'number should be greater than 0') # 测试非整数输入抛出预期异常 def test_non_integer_input_raise_error(self): with self.assertRaises(TypeError) as ctx: calculate_factorial(2.5) self.assertEqual(str(ctx.exception), 'number should be an integer type') if __name__ == '__main__': unittest.main(verbosity=2)
运行后会自动执行所有用例,无需人工输入参数。
内容的提问来源于stack exchange,提问作者trillion
相关产品推荐
相关产品推荐

