框架的最終歸宿往往是領(lǐng)域語(yǔ)言+模板解析。
首先先約定一種所要執(zhí)行操作的表述格式。然后通過(guò)模板解析將描述語(yǔ)言轉(zhuǎn)化為代碼進(jìn)行執(zhí)行。例如炒辉,我們可以使用以下yaml文件描述多個(gè)步驟并且需要關(guān)聯(lián)的接口:
apis.yaml
:
- name: 獲取百度token接口 # 接口名稱
request: # 請(qǐng)求報(bào)文
url: https://aip.baidubce.com/oauth/2.0/token
method: get
params:
grant_type: client_credentials
client_id: kPoFYw85FXsnojsy5bB9hu6x
client_secret: l7SuGBkDQHkjiTPU3m6NaNddD6SCvDMC
extract: # 提取變量, 字典格式
token: RESPONSE.json()['access_token'] # RESPONSE系統(tǒng)變量,代表響應(yīng)對(duì)象
- name: 百度ORC接口 # 第二個(gè)接口
request:
url: https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token=${token} # 使用變量
method: post
data: # 請(qǐng)求體(表單格式)
url: http://upload-images.jianshu.io/upload_images/7575721-40c847532432e852.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
verify: # 斷言, 列表格式
- RESPONSE.json()['words_result_num'] == 6
其中泉手,name
為該接口或步驟的名稱描述黔寇,request
段是接口的信息,對(duì)應(yīng)requests.request()
的每一個(gè)參數(shù)斩萌,url
和method
是必要參數(shù)缝裤,params
,headers
,cookies
,data
, json
,files
,timeout
等,并使用對(duì)應(yīng)格式颊郎。extract用于提取值憋飞, token: RESPONSE.json()['access_token'] ,表示提取該接口響應(yīng)字典中的access_token字段的值保存為名為token的變量姆吭。
在第二個(gè)接口的url中通過(guò)使用${token}榛做,引用該變量。
verify段類似與extract, 計(jì)算表達(dá)式的值内狸,通過(guò)結(jié)果的True/False判斷該條斷言是否通過(guò)检眯。
上面我們定義了一套接口關(guān)聯(lián)的描述及規(guī)則,下面我們要對(duì)我們的規(guī)則進(jìn)行解析答倡,并加載運(yùn)行轰传,主要分為以下幾步:
- 讀取yaml文件并使用
yaml.safe_load(f)
轉(zhuǎn)為列表/字典 - 遍歷列表,每個(gè)列表項(xiàng)是一個(gè)接口
- 讀取當(dāng)前列表項(xiàng)(接口)的request段信息瘪撇,處理${變量}
- 將request段(字典格式)重新轉(zhuǎn)會(huì)yaml字符串
- 如果包含
$
使用string.Template('字符串').safe_subtitute(locals())
获茬,從locals()當(dāng)前所有局部變量中找到$表示的同名變量,如token倔既,并替換恕曲。 - 重新將替換后變量的字符串轉(zhuǎn)化為字典
- 字典拆包,發(fā)送request請(qǐng)求
- 如果請(qǐng)求中有extract字段渤涌,使用
eval()
計(jì)算表達(dá)式的值并保存到局部變量locals()
中佩谣。 - 如果請(qǐng)求中有verify字段,使用
eval()
計(jì)算表達(dá)式的值实蓬,并判斷真假茸俭。
實(shí)現(xiàn)代碼:
需要安裝pyyaml:
pip install pyyaml
apis_parser.py
import yaml
import requests
from string import Template
with open('apis.yaml', encoding='utf-8') as f:
apis = yaml.safe_load(f)
for api in apis:
print("處理請(qǐng)求:", api.get('name'))
request = api.get('request', {}) # 請(qǐng)求報(bào)文,默認(rèn)值為{}
# 處理參數(shù)化請(qǐng)求中的${變量}
request_str = yaml.dump(request) # 先轉(zhuǎn)為字符串
if '$' in request_str:
request_str = Template(request_str).safe_substitute(locals()) # 替換${變量}為局部變量中的同名變量
request = yaml.safe_load(request_str) # 重新轉(zhuǎn)為字典
# 發(fā)送請(qǐng)求
res = requests.request(**request) # 字典解包安皱,發(fā)送接口
# 提取變量
extract = api.get('extract')
if extract is not None: # 如果存在extract
for key, value in extract.items():
# 計(jì)算value表達(dá)式调鬓,可使用的全局變量為空,可使用的局部變量為RESPONSE(響應(yīng)對(duì)象)
# 保存變量結(jié)果到局部變量中
print("提取變量:", key, value)
locals()[key] = eval(value, {}, {'RESPONSE': res})
# 處理斷言
verify = api.get('verify')
if verify is not None:
for line in verify:
result = eval(line, {}, {'RESPONSE': res}) # 計(jì)算斷言表達(dá)式酌伊,True代表成功腾窝,F(xiàn)alse代表失敗
print("斷言:", line, "結(jié)果:", "PASS" if result else "FAIL")
執(zhí)行結(jié)果:
處理請(qǐng)求: 獲取百度token接口
提取變量: token RESPONSE.json()['access_token']
處理請(qǐng)求: 百度ORC接口
斷言: RESPONSE.json()['words_result_num'] == 6 結(jié)果: PASS