自己驅動自己—Python程式碼寫介面測試(一)
背景
在《聊聊介面測試》中我提到了使用Jmeter的問題和侷限性。
這裡其實是有一個問題的。Jmeter的學習成本其實挺大的,基礎的發請求斷言這類功能當然是很簡單,再往後,很多細節上的處理問題,解決起來就非常非常困難,網路上很難找到類似的問題和解決方法,即使是自己去翻官方文件,也不一定就能很快的找到。
那自己寫一個介面測試就迫在眉睫了,本著自己驅動自己的想法,我直接把所有內容寫在程式碼中,自己維護起來也很快。
環境
版本相關
作業系統:Mac OS X EI Caption
Python版本:3.6
IDE:PyCharm
第三方依賴庫:requests
前端:Bootstrap
視覺化:Echarts
思路
這部分主要參考Jmeter的方法。先執行介面測試,然後收集執行結果,寫到一個結果檔案中,再用指令碼去讀這個結果檔案,生成結果報告。Jmeter是使用xml的方式生成一個jmx的結果,我對JSON熟悉一些,就使用JSON來生成結果檔案。
測試報告
整體架構
|____Common.py
|____Debug.py
|____NewLive.py
|____outReport.py
|____report.html
|____reportData.json
|____Run.py
Common.py
Debug.py
是用於編寫單條介面測試用例的檔案,基於Pycharm對unittest
的友好支援,除錯起來非常方便。
NewLive.py
是我的介面測試檔案,裡面放了所有的介面測試用例、執行方法和生成結果檔案的方法。
outReport.py
是讀取結果檔案生成HTML測試報告的指令碼
report.html
是測試報告。
reportData.json
是介面測試檔案生成的結果檔案。
Run.py
是啟動器,執行後就會批量執行介面測試。
注意:本工程只適用於單個介面測試專案,如果有多個介面測試專案,則需要增加一些遍歷的方法。
介面測試檔案
這個檔案是每一個介面測試專案的核心檔案,整個專案的所有介面測試用例和執行方法都在這裡面。
專案的每一個介面,都寫一個類。這個介面的測試用例,在這個類中都以test開頭。
使用unittest
作為框架本是最方便的方法,無奈unittest
方法對於結果檔案的寫入不方便,我又懶得去翻官方文件,於是簡單的自己寫一個啟動方法。
run方法
def run(classInstance):
"""
執行類中的所有以test開頭的方法,前提是初始化的內容要與類中的name屬性一致
:param classInstance:類
:return:None
"""
funcs = []
for x in dir(classInstance):
if x.startswith('test'):
funcs.append(x)
for x in funcs:
eval(classInstance.name+'.'+x+'()')
這個方法是啟動測試的實現方法,run()
方法需要傳入一個類作為引數,方法中需要獲取這個類中的name屬性用來啟動類中的測試用例,因此需要在類中專門定義這個name屬性,並且例項化的時候需要與這個name屬性一致。
介面類
class StartLive:
def __init__(self):
self.classes = []
self.name = 'startlive'
InterFaceInfo = {
'InterFaceName': 'StartLive',
'FuncNo': 'xxx',
'Desc': 'xxx'
}
self.classes.append(InterFaceInfo)
介面類的初始化需要定製一些內容。
self.classes
列表用於收集這個介面的測試情況。
self.name
需要與例項化的名稱一致,用於啟動測試。
InterFaceInfo
說明介面的描述,方便測試報告展示。
測試用例
def test001_StartLiveCommon(self):
"""正常開始直播"""
payload = {
"funcNo": "XXX",
"roomId": "XXX",
"userId": "XXX",
"broadIssue": time.strftime("%H%m%d") + "直播開始",
"broadNotice": time.strftime("%H%m%d") + "直播開始",
}
r = requests.post(url, data=payload)
result = r.json()
try:
assert result['error_no'] == '0'
assert result['error_info'] == '建立直播併發布直播公告成功'
consequence = "success"
except Exception:
consequence = 'error'
rst_data = {
"Url": url,
"desc": "正常開始直播",
"sendData": payload,
"rspData": result,
"result": consequence
}
self.classes.append(rst_data)
由於之前的run()
方法是遍歷以test開頭的方法,因此用例的方法的命名必須以test開頭。
第一部分的payload是請求的引數,第二部分是請求的方法,可以根據自己的需求使用get
或者post
方法。第三部分是斷言部分,斷言成功則給一個成功的標記,斷言失敗則給一個失敗的標記。第四部分是測試結果的收集,資訊包括url、案例描述、傳送資料、接受資料和測試結果,用於最終報告的展示。第五部分就是把這個結果放到介面類初始化時候的容器中。
清理方法
def testTearClass(self):
reportElement.append(self.classes)
在執行完畢之後需要做一下資料收集,因此把初始化中的容器self.classes
列表的內容放到reportElement
這個大容器中。
注意:這個方法必須放在類的最後,確保這個方法是最後一個被執行的,也就確保了所有的測試結果資料都能被收集,當然,由於要被run()方法執行到,因此命名也必須以test開頭
寫結果檔案
if __name__ == '__main__':
startlive = StartLive()
run(startlive)
with codecs.open('reportData.json', 'w', 'utf-8') as f:
data = json.dumps(reportElement, sort_keys=True, indent=4)
f.write(data)
最終檔案的執行需要將類初始化,然後在run()
方法中傳入這個初始化的類,run()
方法就會自動執行所有的測試用例,將結果全部歸集到reportElement
這個容器中。
再呼叫寫json檔案的方法把結果檔案寫出來。
生成測試報告
生成測試報告的核心就是去遍歷這個JSON檔案的內容。
def exportReport(jsonName):
"""
根據結果報告的JSON檔案生成HTML報告
:param jsonName:{str}JSON檔名
:return:None
"""
tableHead = []
trs = []
table = []
global interFaceName
with open(jsonName, 'r') as f:
jsonData = json.loads(f.read())
for x in jsonData: # x表示每個介面的資料
trbody = []
for i, a in enumerate(x):
if i == 0:
interFaceName = a['InterFaceName']
tableHead.append(exportInterfaceTableHead(
"介面名稱: {0}, 介面描述: {1}, 功能號: {2}".format(a['InterFaceName'], a['Desc'], a['FuncNo'])))
else:
trbody.append(
exportTableTr(interFaceName + str(i), a['desc'], a['result'], a['sendData'], a['rspData'],
a['Url']))
trs.append(''.join(trbody))
for x, y in zip(tableHead, removeEmptyInList(trs)):
table.append(x + y + exportBottom())
interFaceTable = ''.join(table)
html = htmlHead('直播介面測試', dashBoardTable(exportDashBoardTable(jsonName))) + interFaceTable + htmlFoot(jsonName)
with codecs.open('report.html', 'w', 'utf-8') as f:
f.write(html)
生成HTML結果的最優方式,肯定是用Django來做一個小後臺,這樣可以用模板引擎來來處理HTML,更加快速和靈活。不過為了懶得折騰後臺,在整個生成結果的方法中,我用的是硬編碼的方式,也就是說我把html的內容全部以字串的形式放在程式碼中。然後用format
方法把一些遍歷的結果放到字串中,最終把所有的字串全部拼接到一起,直接寫到檔案中,就生成了最終的測試報告。
大部分前端展示的內容,都是使用Bootstrap來處理,比較簡單直觀。餅狀圖使用的是百度Echarts。
最後
這只是一個初步的結果,後期在專案增加時,需要做一些改造,比如測試報告的歸檔,測試用例的歸檔等內容,執行方法的優化等等。