一、接口基礎(chǔ)
接口測(cè)試是對(duì)系統(tǒng)和組件之間的接口進(jìn)行測(cè)試,主要是效驗(yàn)數(shù)據(jù)的交換,傳遞和控制管理過(guò)程,以及相互邏輯依賴(lài)關(guān)系。其中接口協(xié)議分為HTTP,RPC,Webservice,Dubbo,RESTful等類(lèi)型。
接口測(cè)試流程
1、需求評(píng)審,熟悉業(yè)務(wù)和需求
2、開(kāi)發(fā)提供接口文檔
3、編寫(xiě)接口測(cè)試用例
4、用例評(píng)審
5、提測(cè)后開(kāi)始測(cè)試
6、提交測(cè)試報(bào)告
兩種常見(jiàn)的?HTTP?請(qǐng)求方法:GET?和?POST
二、項(xiàng)目說(shuō)明
本框架是一套基于Python+Pytest+Requests+Allure+Jenkins而設(shè)計(jì)的數(shù)據(jù)驅(qū)動(dòng)接口自動(dòng)化測(cè)試的框架。
技術(shù)棧
Python、Pytest、Requests、Pactverity、Excel、Json、Mysql、Allure、Logbook、Git、Jenkins
三、接口測(cè)試框架結(jié)構(gòu)圖
四、項(xiàng)目功能
Python+Pytest+Allure+Jenkins接口自動(dòng)化框架,實(shí)現(xiàn)Excel或Json維護(hù)測(cè)試用例,支持?jǐn)?shù)據(jù)庫(kù)操作,利用封裝的請(qǐng)求基類(lèi)調(diào)取相應(yīng)的測(cè)試用例接口,獲取配置文件中的環(huán)境地址與環(huán)境變量,
結(jié)合Pytest進(jìn)行單元測(cè)試,使用LogBook進(jìn)行記錄日志,并生成allure測(cè)試報(bào)告,最后進(jìn)行Jenkins集成項(xiàng)目實(shí)現(xiàn)集成部署,并發(fā)送測(cè)試報(bào)告郵件。
五、代碼設(shè)計(jì)與功能說(shuō)明
1、工具類(lèi)封裝
1.1、log日志
項(xiàng)目中的log日志是logbook進(jìn)行日志記錄的,方便測(cè)試開(kāi)發(fā)調(diào)試時(shí)進(jìn)行排錯(cuò)糾正或修復(fù)優(yōu)化。日志可選擇是否打印在屏幕上即運(yùn)行時(shí)是否在終端輸出打印。日志格式輸出可調(diào)整。
handle_log.py部分源碼
def log_type(record, handler):
log = "[{date}] [{level}] [{filename}] [{func_name}] [{lineno}] {msg}".format(
date=record.time, # 日志時(shí)間
level=record.level_name, # 日志等級(jí)
filename=os.path.split(record.filename)[-1], # 文件名
func_name=record.func_name, # 函數(shù)名
lineno=record.lineno, # 行號(hào)
msg=record.message # 日志內(nèi)容
)
return log
# 日志存放路徑
LOG_DIR = BasePath + '/log'
print(LOG_DIR)
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR)
# 日志打印到屏幕
log_std = ColorizedStderrHandler(bubble=True)
log_std.formatter = log_type
# 日志打印到文件
log_file = TimedRotatingFileHandler(
os.path.join(LOG_DIR, '%s.log' % 'log'), date_format='%Y-%m-%d', bubble=True, encoding='utf-8')
log_file.formatter = log_type
# 腳本日志
run_log = Logger("global_log")
def init_logger():
logbook.set_datetime_format("local")
run_log.handlers = []
run_log.handlers.append(log_file)
run_log.handlers.append(log_std)
打印在終端的日志,如下圖所示。
同時(shí)運(yùn)行項(xiàng)目后,會(huì)在項(xiàng)目文件log中自動(dòng)生成一個(gè)以當(dāng)天日期命名的log文件。點(diǎn)擊log日志文件可查看日志詳情即項(xiàng)目運(yùn)行時(shí)所記錄的日志或報(bào)錯(cuò)日志。如下圖所示。
1.2、配置文件
項(xiàng)目中涉及到一些配置文件如username、password或環(huán)境變量時(shí),我們可通過(guò)配置文件來(lái)獲取配置值。通過(guò)配置文件中key與value的定義來(lái)確定獲取配置文件的值。
handle_init.py部分源碼
class HandleInit:
# 讀取配置文件
def load_ini(self):
file_path = BasePath + "/config/config.ini"
cf = configparser.ConfigParser()
cf.read(file_path, encoding='UTF-8')
return cf
# 獲取ini里面對(duì)應(yīng)key的value
def get_value(self, key, node=None):
if node == None:
node = 'Test'
cf = self.load_ini()
try:
data = cf.get(node, key)
logger.info('獲取配置文件的值,node:{},key:{}, data:{}'.format(node, key, data))
except Exception:
logger.exception('沒(méi)有獲取到對(duì)應(yīng)的值,node:{},key:{}'.format(node, key))
data = None
return data
獲取配置文件中的值日志如下圖所示。
1.3、Api接口請(qǐng)求
獲取相關(guān)測(cè)試用例及接口用例配置,記錄請(qǐng)求相關(guān)參數(shù)的日志,定義Allure測(cè)試報(bào)告的步驟。
handle_apirequest.py部分代碼
class ApiRequest:
def api_request(self, base_url, test_case_data, case_data):
get_name = None
get_url = None
get_method = None
get_headers = None
get_cookies = None
get_case_name = None
get_case_params = None
response_data = None
try:
get_name = test_case_data['config']['name']
get_url = base_url + test_case_data['config']['url']
get_method = test_case_data['config']['method']
get_headers = test_case_data['config']['headers']
get_cookies = test_case_data['config']['cookies']
except Exception as e:
logger.exception('獲取用例基本信息失敗,{}'.format(e))
try:
get_case_name = case_data['name']
get_case_params = case_data['params']
except Exception as e:
logger.exception('獲取測(cè)試用例信息失敗,{}'.format(e))
with allure.step("請(qǐng)求接口:%s,請(qǐng)求地址:%s,請(qǐng)求方法:%s,請(qǐng)求頭:%s,請(qǐng)求Cookies:%s" % (
get_name, get_url, get_method, get_headers, get_cookies)):
allure.attach("接口用例描述:", "{0}".format(get_case_name))
allure.attach("接口用例請(qǐng)求參數(shù):", "{0}".format(get_case_params))
logger.info(
'請(qǐng)求接口名:%r,請(qǐng)求地址:%r,請(qǐng)求方法:%r,請(qǐng)求頭:%r,請(qǐng)求Cookies:%r' %\
1.4、Excel數(shù)據(jù)處理
1.4.1、Excel測(cè)試用例
測(cè)試用例中維護(hù)在Excel文件中,類(lèi)中定義如何獲取Excel中的相關(guān)數(shù)據(jù)(如獲取某個(gè)單元格的內(nèi)容,獲取單元格的行數(shù),以及將數(shù)據(jù)寫(xiě)入Excel中等操作)。
handle_exceldata.py部分源碼
1 class OperationExcel:
2 def __init__(self, file_name=None, sheet_id=None):
3 if file_name:
4 self.file_name = file_name
5 self.sheet_id = sheet_id
6 else:
7 self.file_name = ''
8 self.sheet_id = 0
9 self.data = self.get_data()
10
11 # 獲取sheets的內(nèi)容
12 def get_data(self):
13 data = xlrd.open_workbook(self.file_name)
14 tables = data.sheets()[self.sheet_id]
15 return tables
16
17 # 獲取單元格的行數(shù)
18 def get_lines(self):
19 tables = self.data
20 return tables.nrows
21
22 # 獲取某一個(gè)單元格的內(nèi)容
23 def get_cell_value(self, row, col):
24 return self.data.cell_value(row, col)
1.5、Json數(shù)據(jù)處理
1.5.1、Json測(cè)試用例
1 {
2 "config":{
3 "name":"post接口名",
4 "url":"/langdetect",
5 "method":"POST",
6 "headers":{
7 "Content-Type":"application/json"
8 },
9 "cookies":{
10
11 }
12 },
13 "testcase":[
14 {
15 "name":"測(cè)試用例1",
16 "params":{
17 "query":"測(cè)試"
18 },
19 "validate":[
20 {
21 "check":"status_code",
22 "comparator":"eq",
23 "expect":"200"
24 }
25 ]
26 },
27 {
28 "name":"測(cè)試用例2",
29 "params":{
30 "query":"python"
31 },
32 "validate":[
33 {
34 "check":"msg",
35 "comparator":"eq",
36 "expect":"success"
37 }
38 ]
39 }
40 ]
41 }
1.5.2、Json用例處理
獲取Json文件中里具體字段的值。
handle.json.py部分源碼
1 class HandleJson:
2 # 讀取json文件
3 def load_json(self, file_name):
4 if file_name == None:
5 file_path = ""
6 else:
7 file_path = file_name
8 try:
9 with open(file_path, encoding='UTF-8') as f:
10 data = json.load(f)
11 return data
12 except Exception:
13 print("未找到j(luò)son文件")
14 return {}
15
16 # 讀取json文件里具體的字段值
17 def getJson_value(self, key, file_name):
18 if file_name == None:
19 return ""
20 jsonData = self.load_json(file_name)
21 if key == None:
22 getJsonValue = ""
23 else:
24 getJsonValue = jsonData.get(key)
25 return getJsonValue
2、基類(lèi)封裝
2.1、請(qǐng)求基類(lèi)封裝
接口支持Get、Post請(qǐng)求,調(diào)用requests請(qǐng)求來(lái)實(shí)現(xiàn)接口的調(diào)用與返回。接口參數(shù)包括,接口地址、接口請(qǐng)求參數(shù)、cookie參數(shù)、header參數(shù)。
1 class BaseRequest:
2
3 def send_get(self, url, data, header=None, cookie=None):
4 """
5 Requests發(fā)送Get請(qǐng)求
6 :param url:請(qǐng)求地址
7 :param data:Get請(qǐng)求參數(shù)
8 :param cookie:cookie參數(shù)
9 :param header:header參數(shù)
10 """
11 response = requests.get(url=url, params=data, cookies=cookie, headers=header)
12 return response
13
14 def send_post(self, url, data, header=None, cookie=None):
15 """
16 Requests發(fā)送Post請(qǐng)求
17 :param url:請(qǐng)求地址
18 :param data:Post請(qǐng)求參數(shù)
19 :param data:Post請(qǐng)求參數(shù)
20 :param cookie:cookie參數(shù)
21 :param header:header參數(shù)
22 """
23 response = requests.post(url=url, json=data, cookies=cookie, headers=header)
24 return response
25
26 # 主函數(shù)調(diào)用
27
28 def run_main(self, method, url, data, header, cookie=None):
29 try:
30 result = ''
31 if method.upper() == 'GET':
32 result = self.send_get(url, data, header, cookie)
33 elif method.upper() == 'POST':
34 result = self.send_post(url, data, header, cookie)
35 return result
36 except Exception as e:
37 logger.exception('請(qǐng)求主函數(shù)調(diào)用失?。簕}'.format(e))
3、接口測(cè)試用例編寫(xiě)
3.1、接口測(cè)試用例
引用Pytest來(lái)進(jìn)行接口的單元測(cè)試,通過(guò)JSON中多個(gè)測(cè)試用例來(lái)做為參數(shù)化數(shù)據(jù)驅(qū)動(dòng)。結(jié)合Allure制定相應(yīng)接口的測(cè)試報(bào)告。在接口返回?cái)嘌灾埃覀兿冗M(jìn)行該接口的契約測(cè)試,
我們采用的是Pactverity的全量契約校驗(yàn)測(cè)試。當(dāng)契約測(cè)試通過(guò)時(shí),我們?cè)龠M(jìn)行返回參數(shù)的相關(guān)校驗(yàn)測(cè)試。
test_getRequestJson.py部分源碼
1 @allure.feature('測(cè)試GET請(qǐng)求模塊')
2 class TestRequestOne():
3 @allure.title('測(cè)試標(biāo)題')
4 @allure.testcase('測(cè)試地址:https://www.imooc.com')
5 @pytest.mark.parametrize('case_data', testCaseData['testcase'])
6 def test_requestOne(self, case_data):
7 try:
8 api_response = apiRequest.api_request(baseurl, testCaseData, case_data)
9 api_response_data = api_response.json()
10 # pactverity——全量契約校驗(yàn)
11 config_contract_format = Like({
12 "msg": "成功",
13 "result": 0,
14 "data": EachLike({
15 "word": Like("testng")
16 })
17 })
18 mPactVerify = PactVerify(config_contract_format)
19 try:
20 mPactVerify.verify(api_response_data)
21 logger.info(
22 'verify_result:{},verify_info:{}'.format(mPactVerify.verify_result, mPactVerify.verify_info))
23 assert mPactVerify.verify_result == True
24 except Exception:
25 err_msg = '契約校驗(yàn)錯(cuò)誤'
26 logger.exception('測(cè)試用例契約校驗(yàn)失敗,verify_result:{},verify_info:{}'.format(mPactVerify.verify_result,
27 mPactVerify.verify_info))
28 try:
29 for case_validate in case_data['validate']:
30 logger.info('斷言期望相關(guān)參數(shù):check:{},comparator:{},expect:{}'.format(case_validate['check'],
31 case_validate['comparator'],
32 case_validate['expect']))
33 comparatorsTest.comparators_Assert(api_response, case_validate['check'],
34 case_validate['comparator'], case_validate['expect'])
35 logger.info('測(cè)試用例斷言成功')
36 except Exception as e:
37 logger.exception('測(cè)試用例斷言失敗')
38 except Exception as e:
39 logger.exception('測(cè)試用例請(qǐng)求失敗,原因:{}'.format(e))
3.2、主運(yùn)行
運(yùn)用Pytest和Allure的特性,命令行運(yùn)行測(cè)試用例文件夾,并生成對(duì)應(yīng)的allure測(cè)試報(bào)告。
1 if __name__ == "__main__":
2 pytest.main(['-s', '-v', 'test_case/testRequest/', '-q', '--alluredir', 'reports'])
4、Allure2測(cè)試報(bào)告
當(dāng)我們運(yùn)行主函數(shù)時(shí),并生成對(duì)應(yīng)的測(cè)試用例報(bào)告時(shí),我們可以看到在該文件夾中會(huì)生成對(duì)應(yīng)的json文件的測(cè)試報(bào)告。將json文件的測(cè)試報(bào)告轉(zhuǎn)換成html形式的。命令如下
reports是json格式測(cè)試報(bào)告存放的目錄位置,allure_reports是html測(cè)試報(bào)告文件生成的目錄位置。allure命令如下。
1 allure generate reports -o allure_result/
項(xiàng)目根目錄下的allure_reports文件,存放的是allure生成的測(cè)試報(bào)告??煽闯鑫募掠幸粋€(gè)HTML文件,可通過(guò)Python的編輯器Pycharm來(lái)打開(kāi)該HTML文件(測(cè)試報(bào)告),
或可通過(guò)allure命令來(lái)打開(kāi)該HTML,展示HTML測(cè)試報(bào)告。如下所示。
測(cè)試報(bào)告文件,HTML測(cè)試報(bào)告如下。
allure命令打開(kāi)HTML測(cè)試報(bào)告。命令如下所示。
1 allure open allure_result/
如下圖所示。
打開(kāi)生成的HTML測(cè)試報(bào)告如下圖所示。
5、Jenkins集成
Allure+Jenkins的分享,我之前在Pytest+Allure+Jenkins的博客中已經(jīng)分享過(guò)了。這塊可以出門(mén)左轉(zhuǎn)看看。前期的準(zhǔn)備就不在這里重復(fù)說(shuō)明了。我們就直接來(lái)上手創(chuàng)建Item進(jìn)行相關(guān)配置。
General中GitHub項(xiàng)目地址的配置,將自己項(xiàng)目的Git復(fù)制至項(xiàng)目URL處。如下圖所示。
? 源碼管理設(shè)置。勾選Git,填寫(xiě)相應(yīng)的項(xiàng)目Git地址,Git項(xiàng)目權(quán)限所有者,以及對(duì)應(yīng)的拉取代碼的分支。如下圖所示。
? 配置構(gòu)建命令。選擇“執(zhí)行windows批處理命令”,用python運(yùn)行主函數(shù)運(yùn)行腳本,命令如下圖所示。
? 當(dāng)我們?cè)贘enkins里面成功安裝Allure插件后,直接可以在構(gòu)建后操作中配置Allure的相關(guān)配置。在Pytest+Allure+Jenkins中已經(jīng)說(shuō)明過(guò)的。
Results應(yīng)與項(xiàng)目運(yùn)行時(shí)設(shè)置的Allure生成的Json格式報(bào)告的路徑一致,Report?path為Allure?html報(bào)告結(jié)果生成文件存放的路徑。
排除萬(wàn)難之后,我們就可以用Jenkins來(lái)運(yùn)行項(xiàng)目了。如下圖所示。
測(cè)試報(bào)告詳情頁(yè),如下圖所示。
六、后期優(yōu)化
1、接口測(cè)試用例之間的數(shù)據(jù)依賴(lài)
2、測(cè)試報(bào)告郵件的發(fā)送
。。。。。。
七、感想
? 該框架是在涉及python的知識(shí)點(diǎn)比較多,將接口測(cè)試與契約測(cè)試結(jié)合起來(lái)。該框架是在工作之余學(xué)習(xí)多篇文章,實(shí)戰(zhàn)上手逐步入門(mén)開(kāi)始的,適合新手入門(mén)接口自動(dòng)化實(shí)戰(zhàn)練習(xí),僅供參考學(xué)習(xí)??蚣苤杏胁簧倏蓛?yōu)化點(diǎn)與不足點(diǎn),希望大家多多提建議或想法。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-719276.html
進(jìn)階Python接口自動(dòng)化測(cè)試必備教程(2023全網(wǎng)最詳細(xì))文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-719276.html
到了這里,關(guān)于Python+Pytest+Allure+Git+Jenkins數(shù)據(jù)驅(qū)動(dòng)接口自動(dòng)化測(cè)試框架的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!