装饰器叠加

2019-09-09 17:48:31 浏览数 (2)

在使用pytest allure进行自动化脚本开发的时候,在case头部需要增加很多装饰器才能使报告按照预期格式展示

例如我需要报告展示如下:

报告展示

那我需要编写的代码为:

代码语言:javascript复制
@allure.feature('大模块')
@allure.story('子模块')
@allure.title('这个test_b')
@allure.issue('url', '问题单:xxx')
def test_b():
    print('ok')

现在需要将他们变成一行

代码语言:javascript复制
@compose(feature='大模块', 
         story='子模块', 
         title='这个test_b', 
         issue=('url', '问题单:xxx'))
def test_b():
    print('ok')

为了实现这个目标,先来回忆一下装饰器运行的方式,可以阅读一下「测试开发进阶(四)」。

拿出一部分上面allure代码:

代码语言:javascript复制
@allure.feature('大模块')
def test_b():
    print('ok')

其实就相当于:

代码语言:javascript复制
test_b = allure.feature('大模块')(test_b)

所以整一份就是:

代码语言:javascript复制
test_b = allure.feature('大模块')(
    allure.story('子模块')(
        allure.title('这个test_b')(
            allure.issue('url', '问题单:xxx')(
                test_b)
        )
    )
)

不过按照装饰器的调用顺序的话,应该是allure.issue是第一个,所以要把它整个给倒过来,但是对于allure来说这个顺序并不是很重要。

代码语言:javascript复制
test_b = allure.issue('url', '问题单:xxx')(
    allure.title('这个test_b')(
        allure.story('子模块')(
            allure.feature('大模块')(test_b)
        )
    )
)

编写一个函数接受不定长的参数:

代码语言:javascript复制
def compose(**kwargs):
   pass

因为它要作为一个装饰器,所以需要在内部再写一个函数并返回

代码语言:javascript复制
def compose(**kwargs):
   def deco(f):
      ...
      return f
   return deco

...中出入传入的参数

为了偷懒,所以入参没加上allure,需要人为进行一次处理,使用列表推导式快速的拿到:

代码语言:javascript复制
_kwargs = [('allure.'   key, value) for key, value in kwargs.items()]

按照上面说的需要倒过来执行,所以使用reversed把列表倒一下

每次都重新赋值feval(allurefunc)(f)

代码语言:javascript复制
for allurefunc, param in reversed(_kwargs):
    if param:
        f = eval(allurefunc)(param)(f)
    else:
        f = eval(allurefunc)(f)
return f

为了防止找不到allure模块,增加一下它

代码语言:javascript复制
builtins.__dict__.update({'allure': allure})

完整代码:

https://github.com/zx490336534/ZXTestFrame/blob/master/zxapi/utils/allureoperator.py

代码语言:javascript复制
# -*- coding:utf-8 -*-
"""
@Describe: 简化allure装饰器头部
@Author: zhongxin
@Time: 2019-09-03 19:42
@Email: 490336534@qq.com
"""
import builtins
import allure


def compose(**kwargs):
    """
    将头部ALlure装饰器进行封装
    可以采用:
        feature='主要功能模块'
        story='分支功能模块'
        issue=('', '666')
    的方式入参数
    :param kwargs:
    :return:
    """

    def deco(f):
        builtins.__dict__.update({'allure': allure})
        _kwargs = [('allure.'   key, value) for key, value in kwargs.items()]
        for allurefunc, param in reversed(_kwargs):
            if param:
                f = eval(allurefunc)(param)(f)
            else:
                f = eval(allurefunc)(f)
        return f

    return deco

当然这份代码也可以改变成任意的装饰器叠加

0 人点赞