python+unittest+requests+HTMLRunner編寫介面自動化測試集
問題描述:
搭建介面測試框架,執行用例請求多個不同請求方式的介面
實現步驟:
① 建立配置檔案config.ini,寫入部分公用引數,如介面的基本url、測試報告檔案路徑、測試資料檔案路徑等配置項
1 [DATABASE] 2 data_address = ./data/data.xlsx 3 report_address = ./report/ 4 driver = ./drivers/chromedriver.exe 5 6 [HTTP] 7 base_url = https://***.***.cn//
② 從配置檔案中讀取並返回檔案中內容,或寫入配置檔案的方法,檔案命名 readConfig.py
1 import os 2 import configparser 3 4 # 獲取當前py檔案地址 5 proDir = os.path.split(os.path.realpath(__file__))[0] 6 # 組合config檔案地址 7 configPath = os.path.join(proDir,"config.ini") 8 9 class ReadConfig: 10def __init__(self): 11# 獲取當前路徑下的配置檔案 12self.cf = configparser.ConfigParser() 13self.cf.read(configPath) 14 15def get_config(self,field,key): 16# 獲取配置檔案中的key值 17result = self.cf.get(field,key) 18return result 19 20def set_config(self,field,key,value): 21# 向配置檔案中寫入配置資訊 22fb = open(configPath,'w') 23self.cf.set(field,key,value) 24self.cf.write(fb)
③ 從配置檔案中獲取到介面的基本url後,根據不同的介面請求方式讀取請求體或其他引數資訊,引數資訊從excel中讀取,因此檔案readExcel.py用於讀取並返回excel檔案中內容,或寫入Excel的方法
1 import xlrd 2 import xlutils.copy 3 from Base.readConfig import ReadConfig 4 import time 5 6 class ReadExcel: 7 8def __init__(self,section,field,sheet): 9# 開啟工作表,並定位到sheet 10data_address = ReadConfig().get_config(section,field) 11workbook = xlrd.open_workbook(data_address) 12self.table = workbook.sheets()[sheet] 13 14 15def get_rows(self): 16# 獲取excel行數 17rows = self.table.nrows 18return rows 19 20def get_cell(self,row,col): 21# 獲取單元格資料 22cell_data = self.table.cell(row,col).value 23return cell_data 24 25def get_col(self,col): 26# 獲取整列資料 27col_data = self.table.col_value(col) 28return col_data 29 30 class WriteExcel: 31def __init__(self,section,field,sheet): 32# 開啟工作表 33self.address = ReadConfig().get_config(section,field) 34self.workbook = xlrd.open_workbook(self.address) 35self.wf = xlutils.copy.copy(self.workbook) 36self.ws = self.wf.get_sheet(sheet) 37 38def set_cell(self,row,col,value): 39#設定單元格資料 40self.ws.write(row,col,value) 41 42def save_excel(self,filename,format): 43#獲取當前時間 44self.time = time.strftime("%Y%m%d%H%M%S", time.localtime()) 45#生成檔案的檔名及格式 46self.report = filename + '_' +self.time + format 47#儲存檔案 48self.wf.save(self.report)
④ 將獲取介面的url、請求頭、引數等方法封裝成類並寫入base.py中,用於測試框架中測試集的直接調取
1 from Base.readConfig import ReadConfig 2 from Base.readExcel import ReadExcel 3 4 # 例項化 5 readexcel = ReadExcel('DATABASE','data_address',0) 6 7 class BasePage(object): 8def __init__(self, selenium_driver): 9self.driver = selenium_driver 10 11def get_api(self, row, col): 12# 獲取url 13self.base_url = ReadConfig().get_config('HTTP', 'base_url') 14 15# 獲取excel中的介面地址,與url進行拼接 16self.url = self.base_url + readexcel.get_cell(row, col) 17print(self.url) 18return self.url 19 20def get_cell(self, row, col): 21# 獲取excel單元格資料,獲取介面請求的引數 22self.cell = readexcel.get_cell(row, col) 23return self.cell
⑤ 從base.py檔案獲取到請求地址後,需要組合不同型別的請求方式,如get請求直接將引數與地址進行拼接,或post請求以json資料格式等為請求體請求介面,然後再獲取介面物件,得到介面返回的資料,此過程涉及的方法封裝到request_way.py(注:該例項get請求返回資料格式為jsonp,因此需要jsonp格式資料轉換為json格式的方法)
1 from Base.readExcel import ReadExcel 2 from base import BasePage 3 import requests 4 import urllib.parse 5 import json 6 import re 7 8 # 例項化 9 readexcel = ReadExcel('DATABASE','data_address',0) 10 11 # jsonp格式資料轉換為json格式 12 def jsonp_to_json(_jsonp): 13# 解析jsonp資料格式為json 14try: 15return json.loads(re.match(".*?({.*}).*", _jsonp, re.S).group(1)) 16except: 17raise ValueError('Invalid Input') 18 19 class RequestPage(BasePage): 20# post方式請求,json格式為請求體 21def post_requests(self, url, i): 22# 定義請求資料,獲取excel中引數資訊賦值給data,以json格式拼接好資料 23data_1_json = json.dumps(BasePage(self.driver).get_cell(i, 4)) 24data_2_json = json.dumps(BasePage(self.driver).get_cell(i + 1, 4)) 25data = "{" + data_1_json + ":" + data_2_json + "}" 26print(data) 27# 開啟請求,獲取物件 28response = requests.post(url, data) 29# 列印狀態碼 30print(response) 31return response 32 33# get方式請求 34def get_request(self, url, j): 35# 定義請求資料,獲取excel中引數資訊賦值給values 36#values = {} 37values = BasePage(self.driver).get_cell(j, 4) 38# 如果引數不止一個則對請求資料進行編碼拼接'&' 39#data = urllib.parse.urlencode(values) 40# 將資料與url進行拼接 41req = url + '?' + values 42print(req) 43# 開啟請求,獲取物件 44response = urllib.request.urlopen(req) 45# 列印Http狀態碼 46print(response.status) 47# 讀取伺服器返回的資料,對HTTPResponse型別資料進行讀取操作,bytes格式資料編譯成中文編碼 48the_page = response.read().decode("unicode_escape") 49# 將返回的bytes格式資料先轉換成str,再將返回的jsonp格式資料轉換成json格式 50the_page = jsonp_to_json(str(the_page)) 51return the_page
⑥ 得到介面實際返回結果後,需要與預期結果做比對,判斷用例執行結果,所以封裝校驗類到check.py檔案。校驗方式其一是校驗json陣列內每個數值是否一致,其二是直接簡單校驗陣列中的status值和message是否返回正確
1 from base import BasePage 2 from Base.readExcel import WriteExcel 3 4 # 例項化 5 writeexcel = WriteExcel('DATABASE','data_address',0) 6 7 class CheckPage(BasePage): 8# 校驗json陣列內每個值是否一致 9def check_value(self, i, actualresult, expectresult): 10# 遍歷字典的值value,並將value賦值給實際介面資料的值 11for value in actualresult.values(): 12actualresult_value = value 13# 遍歷字典的值value,並將value賦值給excel中預期資料的值 14for value in expectresult.values(): 15expectresult_value = value 16# 如果實際介面返回的每個鍵值與excel中預期返回的資料的每個鍵值一樣,則介面測試用例執行通過,如果不是則列印預期結果和實際結果,可比較差異 17if actualresult_value == expectresult_value: 18writeexcel.set_cell(i, 8, 'SUCCESS') 19print("介面用例執行結果通過") 20else: 21writeexcel.set_cell(i, 8, 'FAILURE') 22writeexcel.set_cell(i, 7, str(actualresult)) 23print('第', i + 1, '行用例執行失敗:預期結果是', expectresult, '實際結果是', actualresult) 24 25# 儲存測試報告 26writeexcel.save_excel('testreport', '.xls') 27 28 29# 校驗json陣列中的status值和message是否返回成功 30def easy_check_value(self, i, actualresult,expectresult): 31# 判斷實際介面值是否狀態碼和訊息返回成功 32if actualresult['status'] == 1 and actualresult['message'] == '完成': 33writeexcel.set_cell(i, 8, 'SUCCESS') 34print('第', i+1, '行用例執行結果正確,用例通過') 35else: 36writeexcel.set_cell(i, 8, 'FAILURE') 37writeexcel.set_cell(i, 7, str(actualresult)) 38print('第', i + 1, '行用例執行失敗:預期結果是', expectresult, '實際結果是', actualresult) 39 40# 儲存測試報告 41writeexcel.save_excel('testreport', '.xls')
⑦ 最後編寫測試集 testcase.py,其中用例包含有執行post和get方式的請求,增加用例可直接在該檔案繼續新增編寫
1 import unittest 2 from selenium import webdriver 3 from Base.readConfig import ReadConfig 4 from base import BasePage 5 from requests_way import RequestPage 6 from check import CheckPage 7 from packages.HTMLTestRunner import HTMLTestRunner 8 9 driver = webdriver.Chrome(ReadConfig().get_config('DATABASE', 'driver')) 10 11 class SmokeTest(unittest.TestCase): 12#初始化 13def setUp(self): 14self.driver = driver 15 16def test_case_10(self): 17"""以json格式資料為請求體的post方式介面請求""" 18# 獲取url 19self.url = BasePage(self.driver).get_api(1,1) 20 21# 將介面實際返回資料轉換為json可序列化,使用json.dumps()時需要物件相應的型別是json可序列化的 22i = 3 23actualresult = RequestPage(self.driver).post_requests(self.url, i).json() 24 25# 獲取excel中的預期結果 26expectresult = eval(BasePage(self.driver).get_cell(i, 6)) 27 28# 校驗實際介面返回結果和用例預期結果是否一致(校驗json陣列內每個值是否一致) 29CheckPage(self.driver).check_value(i, actualresult, expectresult) 30 31def test_case_11(self): 32"""get方式介面請求""" 33# 獲取url 34self.url = BasePage(self.driver).get_api(8, 1) 35 36# 獲取介面實際返回值與excel中的預期結果 37j = 8 38actualresult = RequestPage(self.driver).get_request(self.url, j) 39expectresult = eval(BasePage(self.driver).get_cell(j, 6)) 40 41# 校驗實際介面返回結果和用例預期結果是否一致(校驗json陣列中的status值和message是否返回成功) 42CheckPage(self.driver).easy_check_value(j, actualresult, expectresult) 43 44# 釋放資源 45def test_case_12(self): 46self.driver.quit() 47 48 49 if __name__ == '__main__': 50#構造測試集合 51suite = unittest.TestSuite() 52suite.addTest(SmokeTest('test_case_10')) 53suite.addTest(SmokeTest('test_case_11')) 54suite.addTest(SmokeTest('test_case_12')) 55 56#建立html檔案 57filename = ReadConfig().get_config('DATABASE', 'report_address') + 'testreport.html' 58fp = open(filename, 'wb') 59 60#執行測試並生成html測試報告 61runner = HTMLTestRunner(stream=fp, description='介面用例執行情況:', title='介面自動化測試報告') 62runner.run(suite) 63 64#關閉檔案 65fp.close()
⑧ 其中涉及HTMLTestRunner.py原生HTML測試報告庫,是用於生成測試報告testreport.html,模組下載後直接整合到該專案
模組下載地址: http://tungwaiyip.info/software/HTMLTestRunner.html
⑨ 以python檔案模式執行指令碼才能生成測試報告
參考: https://www.cnblogs.com/kristin/p/10332815.html
以上,整體框架如下圖
執行方式正確得到以下兩種型別測試報告,excel表和html測試報告