概述:
(what)接口自動(dòng)化是指模擬接口層面的自動(dòng)化。(why)因?yàn)槌杀镜涂删S護(hù)性高逐漸成為自動(dòng)化測(cè)試的主流方向之一疗杉。
一、簡(jiǎn)要說(shuō)明
環(huán)境:Python3.6,Unittest,Requests,Mock,DDT
ParamUnittest = 0.2
configparser = 5.0.0
ddt = 1.4.1
jsonpath = 0.82
mock = 4.0.2
openpyxl = 3.0.4
requests = 2.24.0
HTMLTestRunner= 0.9.1
流程說(shuō)明:讀取EXCEL測(cè)試數(shù)據(jù)->生成測(cè)試用例->執(zhí)行測(cè)試用例->結(jié)果寫(xiě)入EXCEL->生成HTMLTestRunner報(bào)告
模塊昭伸、類(lèi)胀滚、包的設(shè)計(jì)說(shuō)明:
baserequest.py 封裝requests方法,支持(post\get\put)多協(xié)議擴(kuò)展
handle_ini.py 讀取配置文件戴差,包括:域名的配置送爸,email的配置,數(shù)據(jù)庫(kù)的配置,取值規(guī)則的配置
mockvalue.py 封裝mock響應(yīng)值的方法暖释,如依賴(lài)數(shù)據(jù)
Util/handl*.py token處理袭厂,json處理,封裝用來(lái)assert的斷言數(shù)據(jù)處理
RunCase.py 核心代碼球匕。聚合用例集并執(zhí)行纹磺,最后生成報(bào)告
Excel測(cè)試數(shù)據(jù)格式如下圖所示:
二、框架結(jié)構(gòu)與流程
1.框架結(jié)構(gòu)如下圖所示:
2.框架流程圖如下圖所示:
三亮曹、代碼功能分析
1橄杨、Config.ini配置文件
此文件中[server]為域名相關(guān)配置秘症,[json]為json處理規(guī)則相關(guān)配置
[server]
host=測(cè)試
username=測(cè)試
password=測(cè)試
[database]
database=測(cè)試
username=測(cè)試
password=測(cè)試
[json]
token_rule = $..token
2、openpyxl讀取excel數(shù)據(jù)
一個(gè)接口可以定義多條case,get_excel_data為封裝了讀取所有excel中case的方法讥珍,最終存儲(chǔ)到一個(gè)嵌套list中历极。
class HandExcel():
def get_excel_data(self):
"""exccel里面所有的case數(shù)據(jù)以列表嵌套list存儲(chǔ))"""
data_list = []
for i in range(self.get_rows()):
data_list.append(self.get_rows_value(i + 2))
return data_list[:-1]
3、ddt數(shù)據(jù)驅(qū)動(dòng)獲取所有case
在執(zhí)行函數(shù)內(nèi)獲取所有的case衷佃,原理和for循環(huán)相似
@ddt.ddt
class Test_Index(unittest.TestCase)
@ddt.data(*data)
def test_mainindex(self, data):
"""執(zhí)行case主流程"""
case_id = data[0]
i = excel_data.get_rows_number(case_id) # 行號(hào)
is_run = data[2]
if is_run == "yes":
data1 = json.loads(data[7])
is_depend = data[3]
4趟卸、編寫(xiě)測(cè)試用例
@ddt.ddt
class Test_Index(unittest.TestCase):
@ddt.data(*data)
def test_mainindex(self, data):
# 用例描述:調(diào)用商品分類(lèi)接口拿到并根據(jù)依賴(lài)數(shù)據(jù)查詢(xún)商品詳情列表
header = None
get_token = None
is_run = data[2]
if is_run == "yes":
url = data[5]
method = data[6]
expected_method = data[10]
res = BaseRequest.run(method, url, data1, get_token, header)
code = res['meta']["status"]
message = res['meta']["msg"]
if expected_method == "mec":
configmes = handle_result_msg(url, code)
self.assertEqual(configmes, message)
5、運(yùn)行框架的主程序
class RunCase():
def runcase(self): # unittest discover管理case
case_path = os.path.join(base_path, "testCase")
discover = unittest.defaultTestLoader.discover(case_path, pattern="test*.py")
result_path = os.path.join(base_path, "Report", "report.html")
with open(result_path, "wb") as f:
runner = HTTPTestRunner.HTMLTestRunner(stream=f, title="測(cè)試報(bào)告", description="測(cè)試人員:ysz")
runner.run(discover)
6氏义、logs INFO示例
2020-08-13 18:13:06,111 - logs… - INFO - D:\untitled\untitled\shopvinterface\Report\report.html
2020-08-13 18:13:06,112 - logs… - INFO - D:\untitled\untitled\shopvinterface\Run\testcase1_ddt.py
7锄列、Mock部分代碼
def mock_depend():
"""mock依賴(lài)數(shù)據(jù)"""
data = {
"data": {
"id": 1
}
}
depend_value = data.get('data').get('id')
get_data = mock.Mock(return_value=depend_value)
res = get_data
return res()
8、baserequest部分代碼
class BaseRE():
"""基礎(chǔ)請(qǐng)求"""
def send_post(self, url, data, get_token=None, header=None):
"""post請(qǐng)求"""
request = requests.Session() # 自動(dòng)關(guān)聯(lián)session
res = request.post(url=url, data=data, headers=header).json()
if get_token is not None:
"""token寫(xiě)入"""
token = ' '.join(jsonpath.jsonpath(res, '$..token'))
header2 = {"Authorization": token}
write_token(header2, get_token["is_token"])
return res
四惯悠、HTMLTestRunner報(bào)告總覽及Excel結(jié)果
1.HTMLTestRunner報(bào)告總覽如下圖所示:
2.Excel結(jié)果如下圖所示:
五邻邮、jenkins集成
使用jenkins插件生成HTMLTestRunner報(bào)告
六、框架擴(kuò)展優(yōu)化
進(jìn)行中...
七克婶、shell腳本自動(dòng)執(zhí)行框架
使用了shell腳本自動(dòng)執(zhí)行框架筒严,每次執(zhí)行前清空日志,并輸出最新日志到控制臺(tái):
項(xiàng)目Github地址:https://github.com/Keith-Yong/pyapiservice
客官請(qǐng)留步情萤!
點(diǎn)個(gè)贊??再走~~