在讲解装饰器在接口自动化测试项目的应用之前,我们先来介绍一下python装饰器到底是个什么

装饰器

说装饰器就不得不提一下函数这个一等公民了,在python中函数有几个特性先来了解一下

函数的一些特性
  • 函数也是对象

在python中函数也是对象,可以把函数赋值给变量,比如下面这样:

def func(message):
print("打印一条message: {}".format(message)) send_message = func
send_message("123")

我们把函数 func 赋予了变量 send_message,这样之后你调用 send_message,就相当于是调用函数 func()

  • 把函数当做参数

函数也可以当做参数传递给另一个函数使用,比如:

def func(message):
print("打印一条message: {}".format(message)) def call_func(func, message):
func(message)
  • 函数的嵌套

函数的嵌套就是说在函数里再定义一个函数,比如这样:

def call_func(message):
def func(message):
print("打印一条message: {}".format(message))
return func(message)

上面在call_func的内部又定义了一个函数func,并在call_func里调用了这个内部的函数,调用后作为call_func的返回值返回

  • 函数的返回值也可以是函数对象

我们修改一下上面的例子。如下:

def call_func():
def func(message):
print("打印一条message: {}".format(message))
return func result = call_func()
result("hello world")

函数 call_func() 的返回值是函数对象 func 本身,之后,我们将其赋予变量 result,再调用 result(‘hello world’),最后输出了'打印一条message: hello world'.

简单的装饰器
def my_decorator(func):
def wrapper():
print('wrapper of decorator')
func()
return wrapper def greet():
print('hello world') greet = my_decorator(greet)
greet() # 输出
wrapper of decorator
hello world

变量 greet 指向了内部函数 wrapper(),而内部函数 wrapper() 中又会调用原函数 greet(),因此,最后调用 greet() 时,就会先打印'wrapper of decorator',然后输出'hello world'。这里的函数 my_decorator() 就是一个装饰器,它把真正需要执行的函数 greet() 包裹在其中,并且改变了它的行为,但是原函数 greet() 不变.

语法糖@
def my_decorator(func):
def wrapper():
print('wrapper of decorator')
func()
return wrapper @my_decorator
def greet():
print('hello world') greet()

这里的@,我们称之为语法糖,@my_decorator就相当于前面的greet=my_decorator(greet)语句,只不过更加简洁。因此,如果你的程序中有其它函数需要做类似的装饰,你只需在它们的上方加上@decorator就可以了,这样就大大提高了函数的重复利用和程序的可读性。

带参数的装饰器

如果原函数 greet() 是需要接收参数,因为被装饰函数是在装饰器里执行,那就需要把函数接收的参数传递到装饰器里,该怎么办呢?很简单,只需在装饰器的嵌套函数上增加入参就行,比如

def my_decorator(func):
def wrapper(message):
print('wrapper of decorator')
func(message)
return wrapper @my_decorator
def greet(message):
print(message) greet('hello world') # 输出
wrapper of decorator
hello world

不过一般不这么一个个的写,麻烦,直接这样搞:

def my_decorator(func):
def wrapper(*args, **kwargs):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper
装饰器也是可以接收参数的

装饰器还有更大程度的灵活性,可以接受自己定义的参数,可以给装饰器本身传递参数

def repeat(num):
def my_decorator(func):
def wrapper(*args, **kwargs):
for i in range(num):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper
return my_decorator @repeat(4)
def greet(message):
print(message) greet('hello world')
类装饰器

类也可以作为装饰器。类装饰器主要依赖于函数__call__(),每当你调用一个类的示例时,函数__call__()就会被执行一次。

class Request:
def __init__(self, func):
self.func = func
self.num_calls = 0 def __call__(self, *args, **kwargs):
self.num_calls += 1
print('num of calls is: {}'.format(self.num_calls))
return self.func(*args, **kwargs) @Request
def example():
print("hello world") example() # 输出
num of calls is: 1
hello world example() # 输出
num of calls is: 2
hello world ...

这个类装饰器还不支持接收参数,后面我们实战的装饰器时可以支持结束参数的。

装饰器在接口自动化测试项目中应用

至此我们介绍完了装饰器,下面我们基于之前的理论,来进行一次实战。

需求是希望通过装饰器来实现接口的请求,能够自定义请求方法、请求的根路径、公共参数、headers设置等功能。

class Request:

    def __init__(self, url='', method='get'):
''''''
self.url = url # 请求路径
self.method = method # 请求方法
self.func_return = None # 被装饰器标记的方法的返回参数
self.func_im_self = None # 被装饰器标记的方法的类的实例
self.session = None # 当前使用的会话对象 def __call__(self, func):
self.func = func
self.is_class = False
try:
if inspect.getfullargspec(self.func).args[0] == 'self':
self.is_class = True
except IndexError:
pass def fun_wrapper(*args, **kwargs):
# 调用被装饰标记的方法,这个方法会返回请求接口所需要的返回值
self.func_return = self.func(*args, **kwargs) or {}
self.func_im_self = args[0] if self.is_class else object
self.create_url()
self.create_session()
self.session.headers.update(getattr(self.func_im_self, 'headers', {}))
self.decorator_args.update(getattr(self.func_im_self, 'common_params', {}))
self.decorator_args.update(self.func_return)
return Request(self.method, self.url, self.session)
return fun_wrapper
def create_url(self):
"""
生成http请求的url,跟路径和接口路由进行拼接
"""
base_url = getattr(self.func_im_self, 'base_url', '')
self.url = self.func_return.pop('url', None) or self.url
self.url = ''.join([base_url, self.url])

使用的时候要定义一个类,比如下面这样:

class AdvertService:

    def __init__(self):
self.common_params = {} # 定义接口请求的公共参数
self.headers = {} # 定义请求的header
self.base_url = self._config.AD_ADMIN_ROOT_URL @Request(url=“/v3/advert/create”, method='post')
def _create_ad(self, advert: Advert):
return dict(json=advert)

上面的header会被自动的添加的session的header里,common_params也会被添加到参数里,base_url和装饰器里传的url会被拼接成一个完整的url去请求接口。

以上实战的具体代码,当然这只是一部分,并不是完整的,后面争取写个系列文章,将这个接口自动化测试项目整体介绍一下,欢迎大家关注,多多交流!

欢迎大家去 我的博客 瞅瞅,里面有更多关于测试实战的内容哦!!

python装饰器在接口自动化测试中的应用的更多相关文章

  1. python装饰器,迭代器,生成器,协程

    python装饰器[1] 首先先明白以下两点 #嵌套函数 def out1(): def inner1(): print(1234) inner1()#当没有加入inner时out()不会打印输出12 ...

  2. Python 装饰器装饰类中的方法

    title: Python 装饰器装饰类中的方法 comments: true date: 2017-04-17 20:44:31 tags: ['Python', 'Decorate'] categ ...

  3. python装饰器中@wraps作用--修复被装饰后的函数名等属性的改变

    Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Python的functools包中提供了一个叫wraps的de ...

  4. 使用python requests库写接口自动化测试--记录学习过程中遇到的坑(1)

    一直听说python requests库对于接口自动化测试特别合适,但由于自身代码基础薄弱,一直没有实践: 这次赶上公司项目需要,同事小伙伴们一起学习写接口自动化脚本,听起来特别给力,赶紧实践一把: ...

  5. 使用 JsonPath 完成接口自动化测试中参数关联和数据验证(Python语言)

    背景: 接口自动化测试实现简单.成本较低.收益较高,越来越受到企业重视 restful风格的api设计大行其道 json成为主流的轻量级数据交换格式 痛点: 接口关联 也称为关联参数.在应用业务接口中 ...

  6. Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

  7. python 装饰器、递归原理、模块导入方式

    1.装饰器原理 def f1(arg): print '验证' arg() def func(): print ' #.将被调用函数封装到另外一个函数 func = f1(func) #.对原函数重新 ...

  8. 装饰模式和python装饰器

    装饰器和装饰模式 先给出两者的定义: - 装饰器:装饰器是一个非常著名的设计模式,常常被用于有切面需求的场景.较为经典的有插入日志.性能測试.事务处理等. 装饰器是解决这类问题的绝佳设计.有了装饰器, ...

  9. Python装饰器使用技巧

    装饰器 装饰器是程序开发中经常会用到的一个功能,用好了装饰器,开发效率如虎添翼,所以这也是Python面试中必问的问题,但对于好多初次接触这个知识的人来讲,这个功能有点绕,自学时直接绕过去了,然后面试 ...

随机推荐

  1. python信息收集(三)

        前两篇介绍了利用python编写一些脚本实现二层主机的发现,这一篇介绍一下三层主机的发现.     一般来说,三层主机的发现主要是通过ICMP协议来实现的.其中ICMP协议中的ping命令可以 ...

  2. sql语句------合并结果集

    select id,max(val) FROM (select id,a 列名 val from 表名unionselect id,b 列名 val from 表名unionselect id,c 列 ...

  3. MySQL不同存储引擎下optimize的用法

    optimize命令是mysql的常用优化命令,但是在InnoDB与MyISAM这两个存储引擎中却有很大的分别.本文将对这两个常用的存储引擎进行区分跟实例解析 1.查看mysql当前的存储引擎 一般情 ...

  4. Win10 及 Google 浏览器显示界面异常

    win10 和 google 界面显示异常 win10 个别 ui 组件花屏,google 界面直接黑屏 解决方式 更新集成显卡或者重装显卡驱动,最好使用 驱动人生 !!!

  5. 理解分布式一致性:Raft协议

    理解分布式一致性:Raft协议 什么是分布式一致性 Leader选举 日志复制流程 term选举周期 timeout 选举和选举timeout 选举分裂 日志复制和心跳timeout 在分布式系统中, ...

  6. 后缀数组SA

    复杂度:O(nlogn) 注:从0到n-1 const int maxn=1e5; char s[maxn]; int sa[maxn],Rank[maxn],height[maxn],rmq[max ...

  7. ubuntu(物理机)连接ARM开发板

    非虚拟机 ubuntu下连接开发板 首先安装超级终端minicom sudo apt-get install minicom 安装完minicom以后,需要将开发板和电脑进行物理连接.需要使用一条网线 ...

  8. 6.Python中内存是如何管理的?

    Python中内存是如何管理的? Python memory is managed by Python private heap space. All Python objects and data ...

  9. AMD 开源照片级渲染引擎 Radeon ProRender

    除了Radeon Pro WX.Radeon Pro Solid State两款全新的专业显卡,AMD今天还宣布,Radeon ProRender渲染引擎即将开放源代码,开发人员可任意使用.AMD去年 ...

  10. mpvue开发微信小程序之时间+日期选择器

    最近在做微信小程序,技术栈为mpvue+iview weapp组件库. 因项目需求,要用到日期+时间选择器,iview组件库目前还未提供时间日期选择器的组件,小程序官方组件日期时间也是分开的,在简书上 ...