問(wèn)題描述:
搭建接口測(cè)試框架,執(zhí)行用例請(qǐng)求多個(gè)不同請(qǐng)求方式的接口
實(shí)現(xiàn)步驟:
① 創(chuàng)建配置文件config.ini,寫(xiě)入部分公用參數(shù),如接口的基本url、測(cè)試報(bào)告文件路徑、測(cè)試數(shù)據(jù)文件路徑等配置項(xiàng)
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//
② 從配置文件中讀取并返回文件中內(nèi)容,或?qū)懭肱渲梦募姆椒ǎ募?readConfig.py
1 import os
2 import configparser
3
4 # 獲取當(dāng)前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:
10 def __init__(self):
11 # 獲取當(dāng)前路徑下的配置文件
12 self.cf = configparser.ConfigParser()
13 self.cf.read(configPath)
14
15 def get_config(self,field,key):
16 # 獲取配置文件中的key值
17 result = self.cf.get(field,key)
18 return result
19
20 def set_config(self,field,key,value):
21 # 向配置文件中寫(xiě)入配置信息
22 fb = open(configPath,'w')
23 self.cf.set(field,key,value)
24 self.cf.write(fb)
③ 從配置文件中獲取到接口的基本url后,根據(jù)不同的接口請(qǐng)求方式讀取請(qǐng)求體或其他參數(shù)信息,參數(shù)信息從excel中讀取,因此文件readExcel.py用于讀取并返回excel文件中內(nèi)容,或?qū)懭隕xcel的方法
1 import xlrd
2 import xlutils.copy
3 from Base.readConfig import ReadConfig
4 import time
5
6 class ReadExcel:
7
8 def __init__(self,section,field,sheet):
9 # 打開(kāi)工作表,并定位到sheet
10 data_address = ReadConfig().get_config(section,field)
11 workbook = xlrd.open_workbook(data_address)
12 self.table = workbook.sheets()[sheet]
13
14
15 def get_rows(self):
16 # 獲取excel行數(shù)
17 rows = self.table.nrows
18 return rows
19
20 def get_cell(self,row,col):
21 # 獲取單元格數(shù)據(jù)
22 cell_data = self.table.cell(row,col).value
23 return cell_data
24
25 def get_col(self,col):
26 # 獲取整列數(shù)據(jù)
27 col_data = self.table.col_value(col)
28 return col_data
29
30 class WriteExcel:
31 def __init__(self,section,field,sheet):
32 # 打開(kāi)工作表
33 self.address = ReadConfig().get_config(section,field)
34 self.workbook = xlrd.open_workbook(self.address)
35 self.wf = xlutils.copy.copy(self.workbook)
36 self.ws = self.wf.get_sheet(sheet)
37
38 def set_cell(self,row,col,value):
39 #設(shè)置單元格數(shù)據(jù)
40 self.ws.write(row,col,value)
41
42 def save_excel(self,filename,format):
43 #獲取當(dāng)前時(shí)間
44 self.time = time.strftime("%Y%m%d%H%M%S", time.localtime())
45 #生成文件的文件名及格式
46 self.report = filename + '_' +self.time + format
47 #保存文件
48 self.wf.save(self.report)
④ 將獲取接口的url、請(qǐng)求頭、參數(shù)等方法封裝成類(lèi)并寫(xiě)入base.py中,用于測(cè)試框架中測(cè)試集的直接調(diào)取
1 from Base.readConfig import ReadConfig
2 from Base.readExcel import ReadExcel
3
4 # 實(shí)例化
5 readexcel = ReadExcel('DATABASE','data_address',0)
6
7 class BasePage(object):
8 def __init__(self, selenium_driver):
9 self.driver = selenium_driver
10
11 def get_api(self, row, col):
12 # 獲取url
13 self.base_url = ReadConfig().get_config('HTTP', 'base_url')
14
15 # 獲取excel中的接口地址,與url進(jìn)行拼接
16 self.url = self.base_url + readexcel.get_cell(row, col)
17 print(self.url)
18 return self.url
19
20 def get_cell(self, row, col):
21 # 獲取excel單元格數(shù)據(jù),獲取接口請(qǐng)求的參數(shù)
22 self.cell = readexcel.get_cell(row, col)
23 return self.cell
⑤ 從base.py文件獲取到請(qǐng)求地址后,需要組合不同類(lèi)型的請(qǐng)求方式,如get請(qǐng)求直接將參數(shù)與地址進(jìn)行拼接,或post請(qǐng)求以json數(shù)據(jù)格式等為請(qǐng)求體請(qǐng)求接口,然后再獲取接口對(duì)象,得到接口返回的數(shù)據(jù),此過(guò)程涉及的方法封裝到request_way.py(注:該實(shí)例get請(qǐng)求返回?cái)?shù)據(jù)格式為jsonp,因此需要jsonp格式數(shù)據(jù)轉(zhuǎn)換為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 # 實(shí)例化
9 readexcel = ReadExcel('DATABASE','data_address',0)
10
11 # jsonp格式數(shù)據(jù)轉(zhuǎn)換為json格式
12 def jsonp_to_json(_jsonp):
13 # 解析jsonp數(shù)據(jù)格式為json
14 try:
15 return json.loads(re.match(".*?({.*}).*", _jsonp, re.S).group(1))
16 except:
17 raise ValueError('Invalid Input')
18
19 class RequestPage(BasePage):
20 # post方式請(qǐng)求,json格式為請(qǐng)求體
21 def post_requests(self, url, i):
22 # 定義請(qǐng)求數(shù)據(jù),獲取excel中參數(shù)信息賦值給data,以json格式拼接好數(shù)據(jù)
23 data_1_json = json.dumps(BasePage(self.driver).get_cell(i, 4))
24 data_2_json = json.dumps(BasePage(self.driver).get_cell(i + 1, 4))
25 data = "{" + data_1_json + ":" + data_2_json + "}"
26 print(data)
27 # 打開(kāi)請(qǐng)求,獲取對(duì)象
28 response = requests.post(url, data)
29 # 打印狀態(tài)碼
30 print(response)
31 return response
32
33 # get方式請(qǐng)求
34 def get_request(self, url, j):
35 # 定義請(qǐng)求數(shù)據(jù),獲取excel中參數(shù)信息賦值給values
36 #values = {}
37 values = BasePage(self.driver).get_cell(j, 4)
38 # 如果參數(shù)不止一個(gè)則對(duì)請(qǐng)求數(shù)據(jù)進(jìn)行編碼拼接'&'
39 #data = urllib.parse.urlencode(values)
40 # 將數(shù)據(jù)與url進(jìn)行拼接
41 req = url + '?' + values
42 print(req)
43 # 打開(kāi)請(qǐng)求,獲取對(duì)象
44 response = urllib.request.urlopen(req)
45 # 打印Http狀態(tài)碼
46 print(response.status)
47 # 讀取服務(wù)器返回的數(shù)據(jù),對(duì)HTTPResponse類(lèi)型數(shù)據(jù)進(jìn)行讀取操作,bytes格式數(shù)據(jù)編譯成中文編碼
48 the_page = response.read().decode("unicode_escape")
49 # 將返回的bytes格式數(shù)據(jù)先轉(zhuǎn)換成str,再將返回的jsonp格式數(shù)據(jù)轉(zhuǎn)換成json格式
50 the_page = jsonp_to_json(str(the_page))
51 return the_page
⑥ 得到接口實(shí)際返回結(jié)果后,需要與預(yù)期結(jié)果做比對(duì),判斷用例執(zhí)行結(jié)果,所以封裝校驗(yàn)類(lèi)到check.py文件。校驗(yàn)方式其一是校驗(yàn)json數(shù)組內(nèi)每個(gè)數(shù)值是否一致,其二是直接簡(jiǎn)單校驗(yàn)數(shù)組中的status值和message是否返回正確
1 from base import BasePage
2 from Base.readExcel import WriteExcel
3
4 # 實(shí)例化
5 writeexcel = WriteExcel('DATABASE','data_address',0)
6
7 class CheckPage(BasePage):
8 # 校驗(yàn)json數(shù)組內(nèi)每個(gè)值是否一致
9 def check_value(self, i, actualresult, expectresult):
10 # 遍歷字典的值value,并將value賦值給實(shí)際接口數(shù)據(jù)的值
11 for value in actualresult.values():
12 actualresult_value = value
13 # 遍歷字典的值value,并將value賦值給excel中預(yù)期數(shù)據(jù)的值
14 for value in expectresult.values():
15 expectresult_value = value
16 # 如果實(shí)際接口返回的每個(gè)鍵值與excel中預(yù)期返回的數(shù)據(jù)的每個(gè)鍵值一樣,則接口測(cè)試用例執(zhí)行通過(guò),如果不是則打印預(yù)期結(jié)果和實(shí)際結(jié)果,可比較差異
17 if actualresult_value == expectresult_value:
18 writeexcel.set_cell(i, 8, 'SUCCESS')
19 print("接口用例執(zhí)行結(jié)果通過(guò)")
20 else:
21 writeexcel.set_cell(i, 8, 'FAILURE')
22 writeexcel.set_cell(i, 7, str(actualresult))
23 print('第', i + 1, '行用例執(zhí)行失敗:預(yù)期結(jié)果是', expectresult, '實(shí)際結(jié)果是', actualresult)
24
25 # 保存測(cè)試報(bào)告
26 writeexcel.save_excel('testreport', '.xls')
27
28
29 # 校驗(yàn)json數(shù)組中的status值和message是否返回成功
30 def easy_check_value(self, i, actualresult,expectresult):
31 # 判斷實(shí)際接口值是否狀態(tài)碼和消息返回成功
32 if actualresult['status'] == 1 and actualresult['message'] == '完成':
33 writeexcel.set_cell(i, 8, 'SUCCESS')
34 print('第', i+1, '行用例執(zhí)行結(jié)果正確,用例通過(guò)')
35 else:
36 writeexcel.set_cell(i, 8, 'FAILURE')
37 writeexcel.set_cell(i, 7, str(actualresult))
38 print('第', i + 1, '行用例執(zhí)行失?。侯A(yù)期結(jié)果是', expectresult, '實(shí)際結(jié)果是', actualresult)
39
40 # 保存測(cè)試報(bào)告
41 writeexcel.save_excel('testreport', '.xls')
⑦ 最后編寫(xiě)測(cè)試集 testcase.py,其中用例包含有執(zhí)行post和get方式的請(qǐng)求,增加用例可直接在該文件繼續(xù)添加編寫(xiě)
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 #初始化
13 def setUp(self):
14 self.driver = driver
15
16 def test_case_10(self):
17 """以json格式數(shù)據(jù)為請(qǐng)求體的post方式接口請(qǐng)求"""
18 # 獲取url
19 self.url = BasePage(self.driver).get_api(1,1)
20
21 # 將接口實(shí)際返回?cái)?shù)據(jù)轉(zhuǎn)換為json可序列化,使用json.dumps()時(shí)需要對(duì)象相應(yīng)的類(lèi)型是json可序列化的
22 i = 3
23 actualresult = RequestPage(self.driver).post_requests(self.url, i).json()
24
25 # 獲取excel中的預(yù)期結(jié)果
26 expectresult = eval(BasePage(self.driver).get_cell(i, 6))
27
28 # 校驗(yàn)實(shí)際接口返回結(jié)果和用例預(yù)期結(jié)果是否一致(校驗(yàn)json數(shù)組內(nèi)每個(gè)值是否一致)
29 CheckPage(self.driver).check_value(i, actualresult, expectresult)
30
31 def test_case_11(self):
32 """get方式接口請(qǐng)求"""
33 # 獲取url
34 self.url = BasePage(self.driver).get_api(8, 1)
35
36 # 獲取接口實(shí)際返回值與excel中的預(yù)期結(jié)果
37 j = 8
38 actualresult = RequestPage(self.driver).get_request(self.url, j)
39 expectresult = eval(BasePage(self.driver).get_cell(j, 6))
40
41 # 校驗(yàn)實(shí)際接口返回結(jié)果和用例預(yù)期結(jié)果是否一致(校驗(yàn)json數(shù)組中的status值和message是否返回成功)
42 CheckPage(self.driver).easy_check_value(j, actualresult, expectresult)
43
44 # 釋放資源
45 def test_case_12(self):
46 self.driver.quit()
47
48
49 if __name__ == '__main__':
50 #構(gòu)造測(cè)試集合
51 suite = unittest.TestSuite()
52 suite.addTest(SmokeTest('test_case_10'))
53 suite.addTest(SmokeTest('test_case_11'))
54 suite.addTest(SmokeTest('test_case_12'))
55
56 #創(chuàng)建html文件
57 filename = ReadConfig().get_config('DATABASE', 'report_address') + 'testreport.html'
58 fp = open(filename, 'wb')
59
60 #執(zhí)行測(cè)試并生成html測(cè)試報(bào)告
61 runner = HTMLTestRunner(stream=fp, description='接口用例執(zhí)行情況:', title='接口自動(dòng)化測(cè)試報(bào)告')
62 runner.run(suite)
63
64 #關(guān)閉文件
65 fp.close()
⑧ 其中涉及HTMLTestRunner.py原生HTML測(cè)試報(bào)告庫(kù),是用于生成測(cè)試報(bào)告testreport.html,模塊下載后直接集成到該項(xiàng)目
模塊下載地址:http://tungwaiyip.info/software/HTMLTestRunner.html
⑨ 以python文件模式執(zhí)行腳本才能生成測(cè)試報(bào)告
參考:https://www.cnblogs.com/kristin/p/10332815.html
以上,整體框架如下圖
執(zhí)行方式正確得到以下兩種類(lèi)型測(cè)試報(bào)告,excel表和html測(cè)試報(bào)告
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-557342.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-557342.html
?正在學(xué)習(xí)測(cè)試的小伙伴可以通過(guò)點(diǎn)擊下面的小卡片
到了這里,關(guān)于python+unittest+requests+HTMLRunner搭建接口測(cè)試框架,執(zhí)行用例請(qǐng)求多個(gè)不同請(qǐng)求方式的接口的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!