python 裝飾器在介面自動化測試中的應用
在講解裝飾器在介面自動化測試專案的應用之前,我們先來介紹一下 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 去請求介面。
以上實戰的具體程式碼,當然這只是一部分,並不是完整的,後面爭取寫個系列文章,將這個介面自動化測試專案整體介紹一下,歡迎大家關注,多多交流!
部落格原文:https://www.immortalp.com/articles/2020/05/20/1589952737702.html
相關文章
- python裝飾器在介面自動化測試中的應用Python
- 介面測試使用Python裝飾器Python
- Python裝飾器在介面測試中常用場景Python
- 自動化測試在國際軟體測試中的應用
- Python 介面自動化測試Python
- python 桌面應用自動化測試Python
- 驗證碼處理在自動化測試中的應用
- python裝飾器decorator的應用Python
- 感測器在自動駕駛中的應用自動駕駛
- 記錄python介面自動化測試--unittest框架基本應用(第二目)Python框架
- python+pytest介面自動化之測試函式、測試類/測試方法的封裝Python函式封裝
- python+pytest介面自動化(11)-測試函式、測試類/測試方法的封裝Python函式封裝
- Jmeter+Ant+Python 介面自動化測試JMeterPython
- 介面自動化測試
- python+pytest介面自動化(1)-介面測試基礎Python
- python介面自動化測試之介面資料依賴Python
- 技術前沿:AI大模型在自動化測試中的應用例項AI大模型
- 自動化測試在 Kubernetes Operator 開發中的應用:以 OpenTelemetry 為例
- python介面自動化測試之python基礎語法Python
- Python自動化測試~PO模型封裝Python模型封裝
- 自動化裝置測試與自動化測試的區別
- Python中的裝飾器Python
- python自動化測試Python
- 求大神指點思路-python 自動化介面測試Python
- 用python實現selenium 自動化測試Python
- Flutter應用進行自動化測試Flutter
- Python + requests + unittest + ddt 進行介面自動化測試的框架Python框架
- MeterSphere 介面自動化測試應用實踐 - 定時任務構建機器人機器人
- protobuf 介面自動化測試摸索
- 介面自動化測試框架 HttpFPT框架HTTP
- 二、介面自動化測試(2)
- 介面自動化測試 - RobotFramework RESTinstanceFrameworkREST
- ? python 介面自動化 (二)--什麼是介面測試、為什麼要做介面測試 (詳解)Python
- 介面自動化測試錄製工具,讓python selenium自動化測試指令碼開發更加方便Python指令碼
- 介面自動化測試框架搭建的思路框架
- 各位測試大佬可有實用的介面自動化測試平臺推薦?
- python中裝飾器的原理Python
- [python] request 介面測試自動化指令碼轉化為 [locust] 效能測試指令碼Python指令碼