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

如何在装饰器内部嵌套使用装饰器?解决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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 12:55:25