您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關Python如何實現http接口自動化測試,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
接口測試常用的工具有fiddler,postman,jmeter等,使用這些工具測試時,需要了解常用的接口類型和區別,比如我用到的post和get請求,表面上看get用于獲取數據post用于修改數據,兩者傳遞參數的方式也有不一樣,get是直接在url里通過?來連接參數,而post則是把數據放在HTTP的包體內(request body),兩者的本質就是TCP鏈接,并無差別,但是由于HTTP的規定和瀏覽器/服務器的限制,導致他們在應用過程中體現出一些不同。具體的可以參考此博文,講解的比較通俗易懂。這些在工具中可以直接選擇,python需要借助requests包。
確定好接口類型后,需要做的就是準備測試數據和設計測試用例了,測試用例比如說可以判斷返回狀態響應碼,或者對返回數據進行判別等,具體可以參考postman中的echo.collections,對于python可以用unittest來組織測試用例和添加斷言進行判斷。而對于測試數據的準備,需要做到數據和業務盡量分離,即將測試數據參數化,在工具中可以通過添加變量的形式實現,對于python設計到的有關包有xlrd,json,如果需要連接數據庫還需要mysql。
測試完成后生產報告或者發送郵件,也可以使用HTMLTestRunner和smtplib等。
我也從這三大方面進行總結:
1. 接口方法實現和封裝
requests庫可以很好的幫助我們實現HTTP請求,API參考文檔,這里我創建了runmethod.py,里面包含RunMethod類:
這里需要注意就是python默認參數和可選參數要放在必選參數后面,對于相應數據使用json格式進行返回。參數verify=false表示忽略對 SSL 證書的驗證。
2.組織測試和生成報告
使用unittest來組織測試、添加測試用例和斷言,測試報告可以下載HTMLTestRunner.py并放在python安裝路徑lib下即可,代碼如下:
#coding:utf-8 import unittest import json import HTMLTestRunner from mock import mock #from demo import RunMain from runmethod import RunMethod from mock_demo import mock_test import os class TestMethod(unittest.TestCase): def setUp(self): #self.run=RunMain() self.run = RunMethod() def test_01(self): url = 'http://coding.imooc.com/api/cate' data = { 'timestamp':'1507034803124', 'uid':'5249191', 'uuid':'5ae7d1a22c82fb89c78f603420870ad7', 'secrect':'078474b41dd37ddd5efeb04aa591ec12', 'token':'7d6f14f21ec96d755de41e6c076758dd', 'cid':'0', 'errorCode':1001 } #self.run.run_main = mock.Mock(return_value=data) res = mock_test(self.run.run_main,data,url,"POST",data) #res = self.run.run_main(url,'POST',data) print(res) self.assertEqual(res['errorCode'],1001,"測試失敗") @unittest.skip('test_02') def test_02(self): url = 'http://coding.imooc.com/api/cate' data = { 'timestamp':'1507034803124', 'uid':'5249191', 'uuid':'5ae7d1a22c82fb89c78f603420870ad7', 'secrect':'078474b41dd37ddd5efeb04aa591ec12', 'token':'7d6f14f21ec96d755de41e6c076758dd', 'cid':'0' } res = self.run.run_main(url,'GET',data) self.assertEqual(res['errorCode'],1006,"測試失敗") def test_03(self): url = 'http://coding.imooc.com/api/cate' data = { 'timestamp':'1507034803124', 'uid':'5249191', 'uuid':'5ae7d1a22c82fb89c78f603420870ad7', 'secrect':'078474b41dd37ddd5efeb04aa591ec12', 'token':'7d6f14f21ec96d755de41e6c076758dd', 'cid':'0', 'status':11 } res = mock_test(self.run.run_main,data,url,'GET',data) print(res) self.assertGreater(res['status'],10,'測試通過') if __name__ == '__main__': filepath = os.getcwd()+'\\report.html' fp = open(filepath,'wb+') suite = unittest.TestSuite() suite.addTest(TestMethod('test_01')) suite.addTest(TestMethod('test_02')) suite.addTest(TestMethod('test_03')) runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title='this is demo test') runner.run(suite) #unittest.main()
這里setUp()方法用來在測試之前執行,同樣的有tearDown()方法,測試case以test開頭進行編寫,然后使用TestSuit類生成測試套件,將case添加進去,運行run suite即可。當測試用例較多時,可以生成多個測試類別,然后使用TestLoader().LoadTestsFromTestCase(測試類)
生成測試用例,再加入testsuite執行。
在這里,我使用了學習到的mock方法,mock即模擬數據,當我們無法實際執行獲得數據時可以使用mock方法,模擬生成我們需要判別的數據,這里mock_test方法同樣進行了封裝:
#coding:utf-8 from mock import mock def mock_test(mock_method,request_data,url,method,response_data): mock_method = mock.Mock(return_value=response_data) res = mock_method(url,method,request_data) return res
這里模擬的是self.run.run_main()方法,將這個方法的返回值設為response_data,而最終我們要判斷的是返回值res,可以結合test_02對比,
res = self.run.run_main(url,'GET',data)
所以又需要傳入參數url,method,request_data,最后返回相應數據即可,
res = mock_test(self.run.run_main,data,url,'GET',data)
這里我假設返回的數據為data,隨意添加了幾個判斷條件errorCode==1001
和status>10
作為判斷依據。最后生成報告如下:
3 測試數據處理
這一部分主要包括設計測試數據,數據提取和參數化,以及解決數據依賴。這里還是以慕課網上學習的例子為例,主要依據測試目的和使用流程來設計,如下圖:
這里首先涉及到的就是對Excel表格的操作,導入相關庫import xlrd
,先對如上表的測試用例進行配置文件編寫:
class global_var: Id = '0' request_name = '1' url = '2' run = '3' request_way = '4' header = '5' case_depend = '6' data_depend = '7' field_depend = '8' data = '9' expect = '10' result = '11'
再定義返回該列的函數,例如獲取caseId和URL:
def get_id(): return global_var.Id def get_url(): return global_var.url
3.1操作Excel文件
然后我們再編寫操作Excel的模塊,主要包含了對Excel表格的操作,獲取表單、行、列、單元格內容等。
import xlrd from xlutils.copy import copy class OperationExcel: def __init__(self,file_name=None,sheet_id=None): if file_name: self.file_name = file_name self.sheet_id = sheet_id else: self.file_name = '/dataconfig/case1.xls' self.sheet_id = 0 self.data = self.get_data() #獲取sheets的內容 def get_data(self): data = xlrd.open_workbook(self.file_name) tables = data.sheets()[self.sheet_id] return tables #獲取單元格的行數 def get_lines(self): tables = self.data return tables.nrows #獲取某一個單元格的內容 def get_cell_value(self,row,col): return self.data.cell_value(row,col) #寫入數據 def write_value(self,row,col,value): '''寫入excel數據row,col,value''' read_data = xlrd.open_workbook(self.file_name) write_data = copy(read_data) sheet_data = write_data.get_sheet(0) sheet_data.write(row,col,value) write_data.save(self.file_name)
其中寫數據用于將運行結果寫入Excel文件,先用copy復制整個文件,通過get_sheet()獲取的sheet有write()方法。
3.2操作json文件
對于請求數據,我是根據關鍵字從json文件里取出字段,所以還需要json格式的數據文件,如下。對應請求數據中的各個關鍵字:
所以還需要編寫對應操作json文件的模塊:
import json class OperetionJson: def __init__(self,file_path=None): if file_path == None: self.file_path = '/dataconfig/user.json' else: self.file_path = file_path self.data = self.read_data() #讀取json文件 def read_data(self): with open(self.file_path) as fp: data = json.load(fp) return data #根據關鍵字獲取數據 def get_data(self,id): print(type(self.data)) return self.data[id]
讀寫操作使用的是json.load(),json.dump()
傳入的是文件句柄。
3.3 獲得測試數據
在定義好Excel和json操作模塊后,我們將其應用于我們的測試表單,定義一個獲取數據模塊:
from util.operation_excel import OperationExcel import data.data_config from util.operation_json import OperetionJson class GetData: def __init__(self): self.opera_excel = OperationExcel() #去獲取excel行數,就是我們的case個數 def get_case_lines(self): return self.opera_excel.get_lines() #獲取是否執行 def get_is_run(self,row): flag = None col = int(data_config.get_run()) run_model = self.opera_excel.get_cell_value(row,col) if run_model == 'yes': flag = True else: flag = False return flag #是否攜帶header def is_header(self,row): col = int(data_config.get_header()) header = self.opera_excel.get_cell_value(row,col) if header != '': return header else: return None #獲取請求方式 def get_request_method(self,row): col = int(data_config.get_run_way()) request_method = self.opera_excel.get_cell_value(row,col) return request_method #獲取url def get_request_url(self,row): col = int(data_config.get_url()) url = self.opera_excel.get_cell_value(row,col) return url #獲取請求數據 def get_request_data(self,row): col = int(data_config.get_data()) data = self.opera_excel.get_cell_value(row,col) if data == '': return None return data #通過獲取關鍵字拿到data數據 def get_data_for_json(self,row): opera_json = OperetionJson() request_data = opera_json.get_data(self.get_request_data(row)) return request_data #獲取預期結果 def get_expcet_data(self,row): col = int(data_config.get_expect()) expect = self.opera_excel.get_cell_value(row,col) if expect == '': return None return expect def write_result(self,row,value): col = int(data_config.get_result()) self.opera_excel.write_value(row,col,value)
該模塊將Excel操作類實例化后用于操作測試表單,分別獲得測試運行所需的各種條件。
3.4 判斷條件
這里判斷一個case是否通過,是將實際結果和預期結果進行對比,比如,狀態碼status是不是200,或者在返回數據中查看是否含有某一字段:
import json import operator as op class CommonUtil: def is_contain(self, str_one,str_two): ''' 判斷一個字符串是否再另外一個字符串中 str_one:查找的字符串 str_two:被查找的字符串 ''' flag = None #先將返回的res進行格式轉換,unicode轉成string類型 if isinstance(str_one,unicode): str_one = str_one.encode('unicode-escape').decode('string_escape') return op.eq(str_one,str_two) if str_one in str_two: flag = True else: flag = False return flag def is_equal_dict(self,dict_one,dict_two): '''判斷兩個字典是否相等''' if isinstance(dict_one,str): dict_one = json.loads(dict_one) if isinstance(dict_two,str): dict_two = json.loads(dict_two) return op.eq(dict_one,dict_two)
所以我們獲得expec數據和相應數據,再調用這個類別的is_contain()
方法就能判斷。
3.5 數據依賴問題
當我們要執行的某個case的相應數據依賴于前面某個case的返回數據時,我們需要對相應數據進行更新,比如case12的相應數據request_data[數據依賴字段]
的值應該更新于case11的返回數據response_data[依賴的返回字段]
。那么我們就需要先執行case11拿到返回數據,再寫入case12的相應數據,首先對操作Excel的模塊進行更新加入:
#獲取某一列的內容 def get_cols_data(self,col_id=None): if col_id != None: cols = self.data.col_values(col_id) else: cols = self.data.col_values(0) return cols #根據對應的caseid找到對應的行號 def get_row_num(self,case_id): num = 0 cols_data = self.get_cols_data() for col_data in cols_data: if case_id in col_data: return num num = num+1 #根據行號,找到該行的內容 def get_row_values(self,row): tables = self.data row_data = tables.row_values(row) return row_data #根據對應的caseid 找到對應行的內容 def get_rows_data(self,case_id): row_num = self.get_row_num(case_id) rows_data = self.get_row_values(row_num) return rows_data
即我們通過依賴的caseId找到對應的行號,拿到整行的內容。我們默認拿到列0的內容(即caseId)循環整列找到依賴的caseId在第幾行,然后返回整行數據,即實現方法get_rows_data(case_id)
。然后再去執行和更新,我們編寫一個專門處理依賴數據的模塊,同時,為了獲取依賴數據,還需要對獲取數據模塊進行更新如下:
#獲取依賴數據的key def get_depend_key(self,row): col = int(data_config.get_data_depend()) depent_key = self.opera_excel.get_cell_value(row,col) if depent_key == "": return None else: return depent_key #判斷是否有case依賴 def is_depend(self,row): col = int(data_config.get_case_depend()) depend_case_id = self.opera_excel.get_cell_value(row,col) if depend_case_id == "": return None else: return depend_case_id #獲取數據依賴字段 def get_depend_field(self,row): col = int(data_config.get_field_depend()) data = self.opera_excel.get_cell_value(row,col) if data == "": return None else: return data
將方法應用于專門處理依賴數據的模塊:
from util.operation_excel import OperationExcel from base.runmethod import RunMethod from data.get_data import GetData from jsonpath_rw import jsonpath,parse class DependdentData: def __init__(self,case_id): self.case_id = case_id self.opera_excel = OperationExcel() self.data = GetData() #通過case_id去獲取該case_id的整行數據 def get_case_line_data(self): rows_data = self.opera_excel.get_rows_data(self.case_id) return rows_data #執行依賴測試,獲取結果 def run_dependent(self): run_method = RunMethod() row_num = self.opera_excel.get_row_num(self.case_id) request_data = self.data.get_data_for_json(row_num) #header = self.data.is_header(row_num) method = self.data.get_request_method(row_num) url = self.data.get_request_url(row_num) res = run_method.run_main(method,url,request_data) return json.loads(res)#返回數據是字符串需要轉成json格式方便后續查詢 #根據依賴的key去獲取執行依賴測試case的響應,然后返回 def get_data_for_key(self,row): depend_data = self.data.get_depend_key(row) response_data = self.run_dependent() json_exe = parse(depend_data) madle = json_exe.find(response_data) return [math.value for math in madle][0]
其中jsonpath用于找到多層級數據,類似于xpath,即通過依賴字段表示的層級關系在返回數據中找到對應的值,最后再執行該case時把數據更新。
3.6 主流程
把上述所有模塊導入,編寫主流程模塊:
from util.operation_excel import OperationExcel from base.runmethod import RunMethod from data.get_data import GetData from jsonpath_rw import jsonpath,parse class DependdentData: def __init__(self,case_id): self.case_id = case_id self.opera_excel = OperationExcel() self.data = GetData() #通過case_id去獲取該case_id的整行數據 def get_case_line_data(self): rows_data = self.opera_excel.get_rows_data(self.case_id) return rows_data #執行依賴測試,獲取結果 def run_dependent(self): run_method = RunMethod() row_num = self.opera_excel.get_row_num(self.case_id) request_data = self.data.get_data_for_json(row_num) #header = self.data.is_header(row_num) method = self.data.get_request_method(row_num) url = self.data.get_request_url(row_num) res = run_method.run_main(method,url,request_data) return json.loads(res)#返回數據是字符串需要轉成json格式方便后續查詢 #根據依賴的key去獲取執行依賴測試case的響應,然后返回 def get_data_for_key(self,row): depend_data = self.data.get_depend_key(row) response_data = self.run_dependent() json_exe = parse(depend_data) madle = json_exe.find(response_data) return [math.value for math in madle][0]
這樣我們就完成了測試執行,并對結果進行了統計,同時解決了數據依賴問題。
關于Python如何實現http接口自動化測試就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。