最近学习了装饰器,就想着如何把它用到自己自动化框架中去。发现每个脚本都需要设置浏览器模式为三星galaxy s5,属于重复性代码。就想到用装饰器来优化下代码,使得代码都可读性和可复制性更强。
以下是装饰器模块的代码:
#coding=utf-8
from selenium import webdriver
options=webdriver.ChromeOptions()
def set_phone_model(phone_model):
def __deco(func):
def _deco(self,*arg, **kw):
mobile_emulation = {'deviceName': phone_model}
options.add_experimental_option("mobileEmulation", mobile_emulation)
func(self,*arg, **kw)
return options
return _deco
return __deco
以下是使用装饰器的代码,test_Search_By_Name是测试脚本(此处省略了整个类的其他无关部分):
from selenium import webdriver
from util.decorator.PhoneModelDecorator import set_phone_model,options
@set_phone_model('Galaxy S5')
def test_Search_By_Name(self):
browser = webdriver.Chrome(chrome_options=options)
browser.get("https://jdread.jd.com/h5/m/")
使用装饰器之前的代码,test_Search_By_Name是测试脚本(此处省略了整个类的其他无关部分):
from util.decorator.PhoneModelDecorator import set_phone_model,options
from selenium import webdriver
mobile_emulation = {'deviceName': 'Galaxy S5'}
options = webdriver.ChromeOptions()
options.add_experimental_option("mobileEmulation", mobile_emulation)
browser = webdriver.Chrome(chrome_options=options)
装饰器的用法分析:
def deco(s):
def __deco(func):
def _deco(*arg,**kw):
print ("before %s called." %func.__name__,s)
print(func(*arg,**kw))
print (" after %s called." %func.__name__,s)
# 不需要返回func,实际上应返回原函数的返回值
return _deco
return __deco
#闭包:_deco+func
@deco("hello")
def myfunc(a,b):
print (" myfunc() called.")
return a+b
myfunc(1,2)
myfunc(3,4)
总结:
装饰器使用了一个“闭包”的概念
闭包就是:函数返回一个内置函数(_deco)+传入的参数(func函数)
装饰器的规则:
规则1:
函数func上面定义了@deco,那么等价于 执行了func = deco(func)
规则2:
装饰函数deco,必须返回一个闭包(一个内置函数+func)
分析调用过程:
首先myfunc上面放了@deco("hello"),相当于执行了myfunc = deco(myfunc),返回了闭包:__deco(myfunc)+“hello”
然后,__deco(myfunc)返回了一个闭包_deco+myfunc
此时,myfunc已经不再是原来的myfunc而是带有装饰的myfunc,执行了_deco里的逻辑:前置操作( print ("before %s called." %func.name,s)
)+myfunc+后置操作(print (" after %s called." %func.name,s))
网友评论