如何在装饰器内部嵌套使用装饰器?解决pytest用例未收集问题
问题原因与解决方法
为什么test1没被pytest收集?
你的装饰器最后返回的是execute_func()——这是直接执行了包装函数,返回的是执行结果(这里是None),而不是函数本身。pytest只会把可调用的函数识别为测试用例,所以test1变成了None,自然不会被收集。
基础版正确装饰器写法
把返回执行结果改成返回函数对象即可:
import allure def my_decorator(func): @allure.description('desc') @allure.title('title') def execute_func(): func() # 返回函数对象,不是执行结果 return execute_func @my_decorator def test1(): assert 1 == 1 def test_a(): assert 1 == 2
这样pytest就能正常收集test1了。
带参数的装饰器实现(按需应用allure装饰器)
要实现接收name/desc/step参数、按需添加0-3个allure装饰器的功能,需要用三层嵌套的装饰器——外层处理参数,中间层接收被装饰的函数,内层是包装逻辑。
代码示例:
import allure def my_decorator(name=None, desc=None, step=None): # 第一层:接收装饰器参数,返回实际的装饰器函数 def decorator(func): # 定义基础包装函数,支持传递参数给原测试函数 def execute_func(*args, **kwargs): func(*args, **kwargs) # 根据参数按需叠加allure装饰器 if name: execute_func = allure.title(name)(execute_func) if desc: execute_func = allure.description(desc)(execute_func) if step: execute_func = allure.step(step)(execute_func) return execute_func return decorator # 使用示例 @my_decorator(name="验证1等于1", desc="基础断言测试") def test1(): assert 1 == 1 @my_decorator(step="执行数值对比步骤") def test2(): assert 2 == 2 @my_decorator() # 不添加任何allure装饰器 def test3(): assert 3 == 3
补充说明
- 包装函数用
*args, **kwargs是为了兼容带参数的测试函数(比如用到pytest fixture的场景),确保原函数的参数能正常传递。 - 按需添加装饰器的逻辑是:先定义基础包装函数,再根据传入的参数依次用对应的allure装饰器去包装它,最终返回处理后的函数。
内容的提问来源于stack exchange,提问作者Szymon Kołodziej
相关产品推荐
相关产品推荐

