日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python接口测试框架设计_Python3简易接口自动化测试框架设计与实现(中)

發布時間:2025/3/20 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python接口测试框架设计_Python3简易接口自动化测试框架设计与实现(中) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

7、Excel數據讀取

用例是放在Excel中的,用xlrd來讀取數據,寫數據需要用到xluntils,先安裝:

pip install xlrd

pip install xluntils

7.1、讀取配置文件

讀取Excel數據,我們需要知道對應的行和列,列相對固定,在配置文件settings中定義,然后讀取,行作為參數傳入。conf/settings文件中的定義如下:

[excel]

case_no=0

case_name=1

is_run=2

case_level=3

case_header=4

case_cookies=5

req_type=6

case_url=7

case_body=8

expect_result=9

operator=10

actual_result=11

test_result=12

在unitls/load_conf.py中編寫讀取配置的方法,獲取各項列值的方法。lood_conf()函數需要傳入兩個參數:配置項字符串標識符,配置項類型。比如要讀取excel下整數case_url:lood_conf("excel.case_url","int")。class excel_config()下定義返回各項列值的方法。

完整代碼如下:

import configparser

'''

read conf from setting.conf

@:parameter:identstr,value_type

value_type:"int" or "str"

'''

def lood_conf(identstr,value_type):

cf = configparser.ConfigParser()

cf.read("../config/settings.conf")

idenlist = identstr.split('.')

if value_type == "int":

try:

value = cf.getint(idenlist[0],idenlist[1])

return value

except (configparser.NoSectionError ,configparser.NoOptionError) as e:

print(e)

if value_type == "str":

try:

value = cf.get(idenlist[0],idenlist[1])

return value

except (configparser.NoSectionError ,configparser.NoOptionError) as e:

print(e)

'''

獲取url,request body等的列號

'''

class excel_config():

#獲取用例編號的列

def caseno_col(self):

return lood_conf("excel.case_no","int")

def casename_col(self):

return lood_conf("excel.case_name","int")

def isrun_col(self):

#print(lood_conf("excel.is_run","int"))

return lood_conf("excel.is_run","int")

def level_col(self):

return lood_conf("excel.case_level","int")

def header_col(self):

return lood_conf("excel.case_header","int")

def cookies_col(self):

return lood_conf("excel.case_cookies","int")

def reqtype_col(self):

return lood_conf("excel.req_type","int")

def caseurl_col(self):

return lood_conf("excel.case_url","int")

def casebody_col(self):

return lood_conf("excel.case_body","int")

def expectresult_col(self):

return lood_conf("excel.expect_result","int")

def actualresult_col(self):

return lood_conf("excel.actual_result","int")

def testresult_col(self):

return lood_conf("excel.test_result","int")

def test_operator_col(self):

return lood_conf("excel.operator","int")

7.1、編寫Excel操作類

unitls/excel_tool.py中定義了獲取用例編號,用例名稱等方法,需要傳入行。回寫測試結果,回寫實際結果方法需要傳入兩個參數:行,值。完整代碼如下:

#coding:utf-8

import xlrd

from untils.log_trace import *

from xlutils.copy import copy

from untils.load_conf import excel_config

class excel_tool():

def __init__(self,excel_name):

self.curr_excel = xlrd.open_workbook(excel_name)

self.table = self.curr_excel.sheet_by_index(0)

#print(self.table.cell(1,1).value)

#實例化excel_config

self.config = excel_config()

self.rows = self.table.nrows

self.excel_name = excel_name

#獲取用例編號

def get_caseno(self,row):

caseno = self.table.cell(row,self.config.caseno_col()).value

if caseno:

return caseno

else:

logging.info("case no is null")

return None

#獲取用例名稱

def get_casename(self,row):

casename = self.table.cell(row,self.config.casename_col()).value

return casename

#獲取是否運行標志

def get_runflag(self,row):

run_flag = self.table.cell(row,self.config.isrun_col()).value

return run_flag

#獲取用例級別

def get_caselevel(self,row):

caselevel = self.table.cell(row,self.config.level_col()).value

return caselevel

#獲取請求url

def get_caseurl(self,row):

caseurl = self.table.cell(row,self.config.caseurl_col()).value

return caseurl

#獲取請求body

def get_casebody(self,row):

case_body = self.table.cell(row,self.config.casebody_col()).value

return case_body

#獲取header

def get_headerflag(self,row):

headerflag = self.table.cell(row,self.config.header_col()).value

return headerflag

#獲取coocikes

def get_cookiesflag(self,row):

cookiesflag = self.table.cell(row,self.config.cookies_col()).value

return cookiesflag

#獲取請求類型

def get_methodtype(self,row):

method_type = self.table.cell(row,self.config.reqtype_col()).value

return method_type

#獲取預期結果

def get_expectres(self,row):

expect_res = self.table.cell(row,self.config.expectresult_col()).value

return expect_res

#獲取測試結果

def get_testres(self,row):

test_res= self.table.cell(row,self.config.testresult_col()).value

return test_res

#獲取操作符

def get_operator(self,row):

operator = self.table.cell(row,self.config.test_operator_col()).value

return operator

#回寫測試結果到excel

def write_testres(self,row,value):

wbook = copy(xlrd.open_workbook(self.excel_name))

sheet = wbook.get_sheet(0)

sheet.write(row, self.config.testresult_col(), value)

wbook.save(self.excel_name)

#回寫實際結果

def write_actualres(self,row,value):

wbook = copy(xlrd.open_workbook(self.excel_name))

sheet = wbook.get_sheet(0)

sheet.write(row, self.config.actualresult_col(), value)

wbook.save(self.excel_name)

8、用例組裝

有了Excel操作類,就可以方便讀取數據和回填結果了。接下來,在unitls/run_main.py中來組裝用例。組裝之前,先獲取是否運行的標志:

運行標志為N,不組裝,將用例標記為skiiped,回填測試結果到Excel文件中。

運行標志為Y,開始組裝用例并執行,并對比預期結果和實際結果。

用例執行通過,將用例標記為pass,回填測試結果和實際結果,實際結果為接口的返回。

用例執行失敗,將用例標記為failed,回填測試結果和實際結果。

接口鑒權需要用到的headers,先在run_main.py 中寫死,這個問題后面解決,在上面的過程中,增加必要的日志,方便定位問題和查看用例的運行日志。完整代碼如下:

#coding:utf-8

from untils.excel_tool import excel_tool

from untils.send_request import send_request

from untils.log_trace import *

from untils.check_result import CheckResult

import json

headers = {

"X-Token":"0a6db4e59c7fff2b2b94a297e2e5632e"

}

class runner():

def __init__(self):

self.excel = excel_tool("../testcase/test.xls")

self.check = CheckResult()

def join_case(self):

global skip_list,sucess_list,failed_list,skip_list

sucess_list = []

sucess_list = []

failed_list = []

skip_list = []

for row in range(1,self.excel.rows):

no = self.excel.get_caseno(row)

url = self.excel.get_caseurl(row)

isrun = self.excel.get_runflag(row)

name = self.excel.get_casename(row)

level = self.excel.get_caselevel(row)

data = self.excel.get_casebody(row)

expect_res = self.excel.get_expectres(row)

method = self.excel.get_methodtype(row)

hasheader = self.excel.get_headerflag(row)

operator = self.excel.get_operator(row)

if isrun == "Y":

logging.info("Begin to run test case : %s,case number :%s" %(name,no))

logging.info("Request method type is :%s" %method)

logging.info("Request URL:%s" %url)

logging.info("Request Body:%s" %json.dumps(json.loads(data),sort_keys=True,indent=2))

res = send_request(method,url,data=data,headers=headers)

is_sucess = self.check.cmpdict(eval(expect_res),eval(res.text),operator)

print(is_sucess)

if is_sucess:

sucess_list.append(name)

#回寫測試結果

self.excel.write_testres(row,"pass")

#回寫實際結果

self.excel.write_actualres(row,res.text)

logging.info("Test case %s run sucess." %name)

else:

failed_list.append(name)

print("fail",is_sucess)

#回寫測試結果

self.excel.write_testres(row,"failed")

#回寫實際結果

self.excel.write_actualres(row,res.text)

logging.error("Test case %s run fail." %name)

logging.info("Response is:%s" %json.dumps(res.json(),sort_keys=True,indent=2))

else:

skip_list.append(name)

self.excel.write_testres(row,"skipped")

def sum(self):

total = len(sucess_list)+len(failed_list) + len(skip_list)

failed = len(failed_list)

sucess = len(sucess_list)

logging.info("-----------------------------------------------------------")

logging.info("本次一共運行:%s 個用例" %total)

logging.info("本次運行通過:%s 個用例" %sucess)

logging.info("本次運行跳過:%s 個用例" %len(skip_list))

logging.info("跳過的用例:%s" %skip_list)

logging.info("-----------------------------------------------------------")

9、用例運行結果校驗

在untils/run_main.py中方法cmpdict()是用來校驗預期和結果實際結果是否匹配,需要傳入三個參數:預期結果字典,實際結果字典,操作符。在check_result.py中編寫校驗用例結果的方法。目前只支持兩種操作符,equal和notequal,預期結果為字典,其中不能嵌套字典。和完整代碼如下:

from untils.log_trace import *

class CheckResult():

def dict_value(self,key,actual):

try:

if key in actual:

return actual[key]

else:

for keys in actual:

return self.dict_value(key,actual[keys])

except Exception as e:

logging.error(e)

return None

def cmpdict(self,expect,actual,equal):

logging.info("Begin to check result of testcase.")

is_dict = isinstance(expect,dict) and isinstance(actual,dict)

if is_dict:

if equal == "equal":

for key in expect.keys():

if expect[key] == self.dict_value(key,actual):

logging.info("%s is equal to %s" %(expect[key],self.dict_value(key,actual)))

return True

else:

logging.error("%s is not equal to %s" %(expect[key],self.dict_value(key,actual)))

return False

if equal == "notequal":

for key in expect.keys():

if key != self.dict_value(key,actual):

logging.info("%s is not equal to %s" %(expect[key],self.dict_value(key,actual)))

return True

else:

logging.error("%s is equal to %s" %(expect[key],self.dict_value(key,actual)))

return False

else:

logging.error("Operator :%s is not support now,you can define it in file[check_result.py]" %equal)

else:

logging.error("Expect or actual result is not dict,check it in excel. ")

10、運行用例

新建一個名稱為test.xls的Excel,將其放到testcase路徑下,并在Excel中編寫測試用例。接口開發請參考:使用Django開發簡單接口:文章增刪改查,我準備的用例如下:

在untils/untils_test.py中導入run_mian模塊來測試一下:

from untils.run_main import runner

if __name__ == "__main__":

#test_send_request()

runner = runner()

runner.join_case()

runner.sum()

運行untils_test.py,然后去到Excel中查看運行結果:

report路徑下查看測試用例運行日志,如下所示:

Sat, 11 May 2019 19:37:56 INFO check_result.py [line:16] Begin to check result of testcase.

Sat, 11 May 2019 19:37:56 ERROR check_result.py [line:38] Operator :e1qual is not support now,you can define it in file[check_result.py]

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:37] Begin to run test case : 查詢文章,case number :1.0

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:38] Request method type is :GET

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:39] Request URL:http://127.0.0.1:9000/articles

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:40] Request Body:{}

Sat, 11 May 2019 19:37:56 INFO send_request.py [line:25] {'X-Token': '0a6db4e59c7fff2b2b94a297e2e5632e'}

Sat, 11 May 2019 19:37:56 INFO check_result.py [line:16] Begin to check result of testcase.

Sat, 11 May 2019 19:37:56 INFO check_result.py [line:22] BS.200 is equal to BS.200

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:52] Test case 查詢文章 run sucess.

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:62] Response is:{

"all_titles": {

"Hello": "alive",

"amy1": "alive",

"modifytest": "alive",

"useasge of ddt": "alive"

},

"msg": "query articles sucess.",

"status": "BS.200"

}

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:37] Begin to run test case : 新增文章,case number :2.0

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:38] Request method type is :POST

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:39] Request URL:http://127.0.0.1:9000/articles/

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:40] Request Body:{

"content": "useasge of ddt",

"title": "useasge of ddt"

}

Sat, 11 May 2019 19:37:56 INFO send_request.py [line:25] {'X-Token': '0a6db4e59c7fff2b2b94a297e2e5632e'}

Sat, 11 May 2019 19:37:56 INFO check_result.py [line:16] Begin to check result of testcase.

Sat, 11 May 2019 19:37:56 ERROR check_result.py [line:25] BS.200 is not equal to BS.400

Sat, 11 May 2019 19:37:56 ERROR run_main.py [line:60] Test case 新增文章 run fail.

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:62] Response is:{

"msg": "title aleady exist,fail to publish.",

"status": "BS.400"

}

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:37] Begin to run test case : 修改文章,case number :3.0

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:38] Request method type is :POST

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:39] Request URL:http://127.0.0.1:9000/articles/7

Sat, 11 May 2019 19:37:56 INFO run_main.py [line:40] Request Body:{

"content": "modify test",

"title": "modify test"

}

Sat, 11 May 2019 19:37:56 INFO send_request.py [line:25] {'X-Token': '0a6db4e59c7fff2b2b94a297e2e5632e'}

Sat, 11 May 2019 19:37:57 INFO check_result.py [line:16] Begin to check result of testcase.

Sat, 11 May 2019 19:37:57 ERROR check_result.py [line:25] BS.200 is not equal to BS.300

Sat, 11 May 2019 19:37:57 ERROR run_main.py [line:60] Test case 修改文章 run fail.

Sat, 11 May 2019 19:37:57 INFO run_main.py [line:62] Response is:{

"msg": "article is not exists,fail to modify.",

"status": "BS.300"

}

Sat, 11 May 2019 19:37:57 INFO run_main.py [line:37] Begin to run test case : 刪除文章,case number :4.0

Sat, 11 May 2019 19:37:57 INFO run_main.py [line:38] Request method type is :DELETE

Sat, 11 May 2019 19:37:57 INFO run_main.py [line:39] Request URL:http://127.0.0.1:9000/articles/7

Sat, 11 May 2019 19:37:57 INFO run_main.py [line:40] Request Body:{}

Sat, 11 May 2019 19:37:57 INFO send_request.py [line:25] {'X-Token': '0a6db4e59c7fff2b2b94a297e2e5632e'}

Sat, 11 May 2019 19:37:57 INFO check_result.py [line:16] Begin to check result of testcase.

Sat, 11 May 2019 19:37:57 ERROR check_result.py [line:25] BS.200 is not equal to BS.300

Sat, 11 May 2019 19:37:57 ERROR run_main.py [line:60] Test case 刪除文章 run fail.

Sat, 11 May 2019 19:37:57 INFO run_main.py [line:62] Response is:{

"msg": "article is not exists,fail to delete.",

"status": "BS.300"

}

Sat, 11 May 2019 19:37:57 INFO run_main.py [line:74] -----------------------------------------------------------

Sat, 11 May 2019 19:37:57 INFO run_main.py [line:75] 本次一共運行:5 個用例

Sat, 11 May 2019 19:37:57 INFO run_main.py [line:76] 本次運行通過:1 個用例

Sat, 11 May 2019 19:37:57 INFO run_main.py [line:77] 本次運行跳過:1 個用例

Sat, 11 May 2019 19:37:57 INFO run_main.py [line:78] 跳過的用例:['新增文章缺少title']

Sat, 11 May 2019 19:37:57 INFO run_main.py [line:79] -----------------------------------------------------------

11 、小結

框架終于能跑起來了,但是遺留的問題還很多。

很多地方的代碼不夠健壯,這個后面慢慢優化。還有用例校驗支持的運算符比較少。

發送郵件模塊待完成。

Headers的問題如何解決?

如果請求的body比較多,寫在Excel是不是很不美觀呀?這個可以從固定地方讀取文件來完成。

Excel中測試用例有沒有必填項呀?這個可以在運行結果之前進行校驗,必填項缺少,不運行。

最關鍵的一點,如果第二個用例依賴于第一個用例的返回,用例依賴一直是個痛點,下一篇解決。

還有很多問題比如,重試機制,耗時的用例設置超時時間,超時默認為失敗等等.......

作者:秦無殤

總結

以上是生活随笔為你收集整理的python接口测试框架设计_Python3简易接口自动化测试框架设计与实现(中)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。