You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python自定义阶乘函数unittest单元测试运行异常问题咨询

问题1:负值输入测试结果不稳定的原因

代码执行顺序存在错误:Python是从上到下逐行解释执行的,你将while交互循环和unittest.main()调用写在了TestCalc测试类的定义之前。第一次进入循环调用单元测试框架时,TestCalc类还没有被加载识别,unittest找不到任何测试用例,就会直接输出RAN OK,相当于没有执行任何测试。只有当你输入-9999退出循环后,Python才会执行到测试类的定义代码,后续再调用测试框架才会真正执行用例,出现负值输入报错的结果,这就是测试结果不稳定的核心原因。

问题2:移除负值判断后负值输入依然显示测试通过的原因

和问题1的根源完全一致:测试用例根本没有被执行。
额外补充第二版代码的逻辑问题:当传入负值时,range(number)会生成空序列,reduce的初始值为1,最终会返回1,而math.factorial(n)传入负值会直接抛出ValueError,如果测试用例真的执行,一定会报错,不可能通过。

问题3:测试方法不需要传参就能访问n的原因

你通过输入得到的n是全局作用域的变量,Python的变量查找规则是:局部作用域找不到的变量,会逐层往上层作用域查找,直到全局作用域。所以测试方法中虽然没有定义n、也没有设置接收参数,依然可以直接读取全局的n值。但这是非常不规范的写法,单元测试不应该依赖全局可变变量,也不应该和人工输入耦合。


规范的单元测试写法参考

单元测试应该是可重复、不依赖人工输入的,推荐提前预设多组测试用例执行测试。如果一定要保留交互式输入的测试逻辑,需要调整代码顺序,先定义函数、测试类,再写交互逻辑:

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_number(self):
        test_cases = [0,1,2,5,10]
        for n in test_cases:
            self.assertEqual(calculate_factorial(n), math.factorial(n))
    
    # 测试负值输入是否抛出预期异常
    def test_negative_number(self):
        with self.assertRaises(ValueError):
            calculate_factorial(-1)
            calculate_factorial(-10)
    
    # 测试非整数输入是否抛出预期异常
    def test_non_int_type(self):
        with self.assertRaises(TypeError):
            calculate_factorial(1.5)
            calculate_factorial("3")

if __name__ == '__main__':
    # 交互式测试逻辑放在最后
    interactive = input("是否进入交互式测试?输入y进入,否则执行预设用例:")
    if interactive == 'y':
        while True:
            n = int(input('Enter an integer value: '))
            if n == -9999:
                break
            try:
                res = calculate_factorial(n)
                assert res == math.factorial(n)
                print(f"测试通过,结果是{res}")
            except Exception as e:
                print(f"测试不通过,错误:{e}")
    else:
        unittest.main()

内容的提问来源于stack exchange,提问作者trillion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 19:48:00