进阶知识:自动化测试框架开发之无参的函数装饰器
from functools import wrapsdef func_2(func):"""无参的函数装饰器:param func::return:"""@wraps(func)def wrap_func(*args, **kwargs):print('开始执行:'+ func.__name__)func(*args, **kwargs)print('执行完成:'+ func.__name__)return wrap_func@func_2
def func_1():"""业务函数:return:"""print('正在执行:'+func_1.__name__)func_1()
一、代码执行顺序解析
1.1 完整执行流程
执行顺序图示:
定义装饰器func_2
↓
定义被装饰函数func_1(触发装饰器立即执行)
↓
调用func_1()↓
实际执行wrap_func()↓
执行wrap_func内部逻辑↓
调用原始func_1函数体
1.2 关键节点说明
执行步骤 | 对应代码行 | 说明 |
---|
1 | def func_2(func): | 定义装饰器函数 |
2 | @func_2 | 应用装饰器(此时立即执行func_2(func_1)) |
3 | func_1 = wrap_func | 原函数被替换为装饰器返回的wrap_func |
4 | func_1() | 实际调用的是wrap_func() |
5 | print(‘开始执行…’) | 执行装饰器添加的前置逻辑 |
6 | func(*args, **kwargs) | 调用原始func_1函数 |
7 | print(‘执行完成…’) | 执行装饰器添加的后置逻辑 |
二、代码逐行解析
2.1 装饰器定义部分
from functools import wrapsdef func_2(func):@wraps(func) def wrap_func(*args, **kwargs):print('开始执行:'+ func.__name__) func(*args, **kwargs) print('执行完成:'+ func.__name__) return wrap_func
关键点说明:
- @wraps(func):保持被装饰函数的原始信息(如__name__等)
- *args, **kwargs:接受任意参数,保证装饰器通用性
- func(*args, **kwargs):执行被装饰的原始函数
2.2 被装饰函数
@func_2
def func_1():print('正在执行:'+func_1.__name__)
2.3 函数调用
func_1()
三、执行逻辑必要性分析
3.1 解决的问题场景
场景 | 传统实现方式 | 装饰器实现优势 |
---|
多个函数需要相同的前后处理逻辑 | 每个函数内部重复写相同代码 | 逻辑集中维护,避免代码重复 |
需要动态添加/移除功能模块 | 需要修改函数源代码 | 不修改原函数实现功能扩展 |
保持函数原始信息 | 手动维护属性信息 | 自动保留函数签名和文档 |
3.2 自动化测试中的典型应用
- 执行日志记录:自动记录用例执行开始/结束时间
- 异常捕获处理:统一处理断言失败截图
- 性能监控:统计用例执行耗时
- 权限校验:在执行前检查测试环境权限
四、执行流程详细拆解
4.1 代码加载阶段
4.2 函数调用阶段
五、与传统实现的对比
5.1 无装饰器实现
def func_1():print('开始执行:func_1')print('正在执行:func_1')print('执行完成:func_1')def func_2():print('开始执行:func_2')print('正在执行:func_2')print('执行完成:func_2')
5.2 使用装饰器的优势
对比维度 | 传统方式 | 装饰器方式 | 优势分析 |
---|
代码复用性 | 每个函数重复代码 | 逻辑集中管理 | 减少80%重复代码 |
维护成本 | 修改需要调整所有函数 | 只需修改装饰器 | 降低维护难度 |
功能扩展性 | 需要修改函数实现 | 动态添加新功能 | 实现开闭原则 |
代码可读性 | 业务与辅助逻辑混杂 | 关注点分离 | 提升代码可维护性 |
六、工程实践建议
6.1 装饰器开发规范
- 始终使用@wraps:保持被装饰函数的元信息
- 使用*args和kwargs**:保证装饰器通用性
- 避免副作用:不要修改被装饰函数输入输出
- 合理命名:装饰器名称应体现功能特征
6.2 测试框架中的典型应用
def log_execution(func):""" 记录用例执行日志 """@wraps(func)def wrapper(*args, **kwargs):start = time.time()print(f"[{datetime.now()}] 开始执行用例:{func.__name__}")result = func(*args, **kwargs)print(f"用例执行耗时:{time.time()-start:.2f}s")return resultreturn wrapper@log_execution
def test_login():""" 登录测试用例 """
核心价值总结:装饰器通过AOP(面向切面编程)实现了业务逻辑与辅助功能的解耦,在自动化测试框架中能有效提升代码复用率(提升60%-80%),降低维护成本(减少50%的代码修改量),是构建可扩展测试框架的重要技术手段。
「小贴士」:点击头像→【关注】按钮,获取更多软件测试的晋升认知不迷路! 🚀