如何测试Python函数是否调用了range对象?
如何测试Python函数是否调用了range对象
方案1:使用unittest.mock动态捕获调用
这是最可靠的动态测试方法,通过替换range为mock对象,记录它是否被调用。
测试函数实现
from unittest.mock import patch def test_range(student_avg_func): # 传入学生编写的avg函数作为参数 with patch('__main__.range') as mock_range: # 让mock的range返回真实range的结果,避免avg函数执行出错 mock_range.side_effect = range # 调用学生的函数,传入测试用的列表 student_avg_func([1, 2, 3, 4]) # 返回range是否被调用的布尔值 return mock_range.called
原理说明
patch('__main__.range')会在上下文管理器内,将当前模块中的range替换为一个mock对象side_effect = range保证当mock的range被调用时,会返回真实range生成的序列,确保学生的avg函数能正常完成计算- 调用学生的avg函数后,通过
mock_range.called属性可以直接判断range是否被调用过
方案2:通过字节码静态检查
如果不需要执行函数,也可以通过反编译函数的字节码,静态检查是否引用了range。
测试函数实现
import dis def test_range(student_avg_func): # 获取函数的字节码指令 for instr in dis.get_instructions(student_avg_func): # 检查是否有加载全局变量range的指令 if instr.opname == 'LOAD_GLOBAL' and instr.argval == 'range': return True return False
原理说明
dis.get_instructions会解析函数的字节码,返回所有执行指令- 当函数中使用
range时,会生成LOAD_GLOBAL指令并加载名为range的全局对象,通过检查这个指令即可判断是否引用了range
注意事项
如果学生通过from builtins import range导入range,判断条件依然有效;但如果是从其他自定义模块导入range,需要调整检查的argval值。
测试示例
假设学生提交的符合要求的avg函数如下:
def avg(lst): if not lst: return 0 total = 0 # 使用range遍历列表索引 for i in range(len(lst)): total += lst[i] return total / len(lst)
调用test_range(avg)会返回True;如果学生未使用range(比如直接for num in lst:遍历),则返回False。
内容的提问来源于stack exchange,提问作者Amit Bloomberg
相关产品推荐
相关产品推荐

