国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

python+requests接口自動(dòng)化框架的實(shí)現(xiàn)

這篇具有很好參考價(jià)值的文章主要介紹了python+requests接口自動(dòng)化框架的實(shí)現(xiàn)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

為什么要做接口自動(dòng)化框架

1、業(yè)務(wù)與配置的分離

2、數(shù)據(jù)與程序的分離;數(shù)據(jù)的變更不影響程序

3、有日志功能,實(shí)現(xiàn)無(wú)人值守

4、自動(dòng)發(fā)送測(cè)試報(bào)告

5、不懂編程的測(cè)試人員也可以進(jìn)行測(cè)試

正常接口測(cè)試的流程是什么?

確定接口測(cè)試使用的工具----->配置需要的接口參數(shù)----->進(jìn)行測(cè)試----->檢查測(cè)試結(jié)果----->生成測(cè)試報(bào)告

測(cè)試的工具:python+requests

接口測(cè)試用例:excel

一、接口框架如下:

python+requests接口自動(dòng)化框架的實(shí)現(xiàn),python,軟件測(cè)試,程序員,接口測(cè)試,自動(dòng)化測(cè)試,測(cè)試工程師

1、action包:用來(lái)存放關(guān)鍵字函數(shù)

2、config包:用來(lái)存放配置文件

3、TestData:用來(lái)存放測(cè)試數(shù)據(jù),excel表

4、Log包:用來(lái)存放日志文件

5、utils包:用來(lái)存放公共的類

6、運(yùn)行主程序interface_auto_test.py

7、Readme.txt:告訴團(tuán)隊(duì)組員使用改框架需要注意的地方

二、接口的數(shù)據(jù)規(guī)范設(shè)計(jì)---Case設(shè)計(jì)

一個(gè)sheet對(duì)應(yīng)數(shù)據(jù)庫(kù)里面一張表

python+requests接口自動(dòng)化框架的實(shí)現(xiàn),python,軟件測(cè)試,程序員,接口測(cè)試,自動(dòng)化測(cè)試,測(cè)試工程師

APIsheet存放
編號(hào);從1開(kāi)始
接口的名稱(APIName);
請(qǐng)求的url(RequestUrl);
請(qǐng)求的方法(RequestMethod);
傳參的方式(paramsType):post/get請(qǐng)求方法不一樣
用例說(shuō)明(APITestCase)
是否執(zhí)行(Active)部分接口已測(cè)通,下次不用測(cè)試,直接把這里設(shè)置成N,跳過(guò)此接口

post與get的區(qū)別

查看post詳情

post請(qǐng)求參數(shù)一般是json串,參數(shù)放在from表單里面;參數(shù)一般不可見(jiàn),相對(duì)來(lái)說(shuō)安全性高些

python+requests接口自動(dòng)化框架的實(shí)現(xiàn),python,軟件測(cè)試,程序員,接口測(cè)試,自動(dòng)化測(cè)試,測(cè)試工程師

查看get詳情

get請(qǐng)求參數(shù)一般直接放在url里面

python+requests接口自動(dòng)化框架的實(shí)現(xiàn),python,軟件測(cè)試,程序員,接口測(cè)試,自動(dòng)化測(cè)試,測(cè)試工程師

2.1注冊(cè)接口用例

python+requests接口自動(dòng)化框架的實(shí)現(xiàn),python,軟件測(cè)試,程序員,接口測(cè)試,自動(dòng)化測(cè)試,測(cè)試工程師

RequestData:請(qǐng)求的數(shù)據(jù)
(開(kāi)發(fā)制定的傳參方式)
RelyData:數(shù)據(jù)依賴
ResponseCode:響應(yīng)code
ResponseData:響應(yīng)數(shù)據(jù)
DataStore:存儲(chǔ)的依賴數(shù)據(jù);如果存在數(shù)據(jù)庫(kù)里面,在表里增加一個(gè)字段用來(lái)存依賴的數(shù)據(jù)
(存儲(chǔ)的方式是編寫接口自動(dòng)化的人員來(lái)設(shè)定的存儲(chǔ)方式)
CheckPoint:檢查點(diǎn)
Active:是否執(zhí)行
Status:執(zhí)行用例的狀態(tài),方便查看用例是否執(zhí)行成功
ErrorInfo:case運(yùn)行失敗,失敗的錯(cuò)誤信息;eg:是也本身的原因還是case設(shè)置失敗,還是其他原因

2.2登錄接口用例

python+requests接口自動(dòng)化框架的實(shí)現(xiàn),python,軟件測(cè)試,程序員,接口測(cè)試,自動(dòng)化測(cè)試,測(cè)試工程師

RequestData:請(qǐng)求的數(shù)據(jù)
(開(kāi)發(fā)制定的傳參方式)
RelyData:數(shù)據(jù)依賴
(存儲(chǔ)的方式是編寫接口自動(dòng)化的人員來(lái)設(shè)定的存儲(chǔ)方式)
ResponseCode:響應(yīng)code
ResponseData:響應(yīng)數(shù)據(jù)
DataStore:存儲(chǔ)的依賴數(shù)據(jù);如果存在數(shù)據(jù)庫(kù)里面,在表里增加一個(gè)字段用來(lái)存依賴的數(shù)據(jù)
(存儲(chǔ)的方式是編寫接口自動(dòng)化的人員來(lái)設(shè)定的存儲(chǔ)方式)
CheckPoint:檢查點(diǎn)
Active:是否執(zhí)行
Status:執(zhí)行用例的狀態(tài),方便查看用例是否執(zhí)行成功
ErrorInfo:case運(yùn)行失敗,失敗的錯(cuò)誤信息;eg:是也本身的原因還是case設(shè)置失敗,還是其他原因

重點(diǎn)說(shuō)明下RelyData:數(shù)據(jù)依賴
采取的是字典:key:value來(lái)存儲(chǔ)數(shù)據(jù)格式;
{"request":{"username":"register->1","password":"register->1"},"response":{"code":"register->1"}}

格式化之后:

1

2

3

4

5

6

7

8

9

{

??"request":{

????"username":"register->1",

????"password":"register->1"

??},

??"response":{

????"code":"register->1"

??}

}

三、創(chuàng)建utils包:用來(lái)存放公共的類

3.1 ParseExcel.py 操作封裝excel的類(ParseExcel.py)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

#encoding=utf-8

import openpyxl

from openpyxl.styles import Border, Side, Font

import time

class ParseExcel(object):

??def __init__(self):

????self.workbook = None

????self.excelFile = None

????self.font = Font(color = None) # 設(shè)置字體的顏色

????# 顏色對(duì)應(yīng)的RGB值

????self.RGBDict = {'red': 'FFFF3030', 'green': 'FF008B00'}

??def loadWorkBook(self, excelPathAndName):

????# 將excel文件加載到內(nèi)存,并獲取其workbook對(duì)象

????try:

??????self.workbook = openpyxl.load_workbook(excelPathAndName)

????except Exception as err:

??????raise err

????self.excelFile = excelPathAndName

????return self.workbook

??def getSheetByName(self, sheetName):

????# 根據(jù)sheet名獲取該sheet對(duì)象

????try:

??????# sheet = self.workbook.get_sheet_by_name(sheetName)

??????sheet = self.workbook[sheetName]

??????return sheet

????except Exception as err:

??????raise err

??def getSheetByIndex(self, sheetIndex):

????# 根據(jù)sheet的索引號(hào)獲取該sheet對(duì)象

????try:

??????# sheetname = self.workbook.get_sheet_names()[sheetIndex]

??????sheetname = self.workbook.sheetnames[sheetIndex]

????except Exception as err:

??????raise err

????# sheet = self.workbook.get_sheet_by_name(sheetname)

????sheet = self.workbook[sheetname]

????return sheet

??def getRowsNumber(self, sheet):

????# 獲取sheet中有數(shù)據(jù)區(qū)域的結(jié)束行號(hào)

????return sheet.max_row

??def getColsNumber(self, sheet):

????# 獲取sheet中有數(shù)據(jù)區(qū)域的結(jié)束列號(hào)

????return sheet.max_column

??def getStartRowNumber(self, sheet):

????# 獲取sheet中有數(shù)據(jù)區(qū)域的開(kāi)始的行號(hào)

????return sheet.min_row

??def getStartColNumber(self, sheet):

????# 獲取sheet中有數(shù)據(jù)區(qū)域的開(kāi)始的列號(hào)

????return sheet.min_column

??def getRow(self, sheet, rowNo):

????# 獲取sheet中某一行,返回的是這一行所有的數(shù)據(jù)內(nèi)容組成的tuple,

????# 下標(biāo)從1開(kāi)始,sheet.rows[1]表示第一行

????try:

??????rows = []

??????for row in sheet.iter_rows():

????????rows.append(row)

??????return rows[rowNo - 1]

????except Exception as err:

??????raise err

??def getColumn(self, sheet, colNo):

????# 獲取sheet中某一列,返回的是這一列所有的數(shù)據(jù)內(nèi)容組成tuple,

????# 下標(biāo)從1開(kāi)始,sheet.columns[1]表示第一列

????try:

??????cols = []

??????for col in sheet.iter_cols():

????????cols.append(col)

??????return cols[colNo - 1]

????except Exception as err:

??????raise err

??def getCellOfValue(self, sheet, coordinate = None,

????????????rowNo = None, colsNo = None):

????# 根據(jù)單元格所在的位置索引獲取該單元格中的值,下標(biāo)從1開(kāi)始,

????# sheet.cell(row = 1, column = 1).value,

????# 表示excel中第一行第一列的值

????if coordinate != None:

??????try:

????????return sheet[coordinate]

??????except Exception as err:

????????raise err

????elif coordinate is None and rowNo is not None and \

????????????colsNo is not None:

??????try:

????????return sheet.cell(row = rowNo, column = colsNo).value

??????except Exception as err:

????????raise err

????else:

??????raise Exception("Insufficient Coordinates of cell !")

??def getCellOfObject(self, sheet, coordinate = None,

????????????rowNo = None, colsNo = None):

????# 獲取某個(gè)單元格的對(duì)象,可以根據(jù)單元格所在位置的數(shù)字索引,

????# 也可以直接根據(jù)excel中單元格的編碼及坐標(biāo)

????# 如getCellObject(sheet, coordinate = 'A1') or

????# getCellObject(sheet, rowNo = 1, colsNo = 2)

????if coordinate != None:

??????try:

????????# return sheet.cell(coordinate = coordinate)

????????return sheet[coordinate]

??????except Exception as err:

????????raise err

????elif coordinate == None and rowNo is not None and \

????????????colsNo is not None:

??????try:

????????return sheet.cell(row = rowNo,column = colsNo)

??????except Exception as err:

????????raise err

????else:

??????raise Exception("Insufficient Coordinates of cell !")

??def writeCell(self, sheet, content, coordinate = None,

????rowNo = None, colsNo = None, style = None):

????#根據(jù)單元格在excel中的編碼坐標(biāo)或者數(shù)字索引坐標(biāo)向單元格中寫入數(shù)據(jù),

????# 下標(biāo)從1開(kāi)始,參style表示字體的顏色的名字,比如red,green

????if coordinate is not None:

??????try:

????????# sheet.cell(coordinate = coordinate).value = content

????????sheet[coordinate] = content

????????if style is not None:

??????????sheet[coordinate].\

????????????font = Font(color = self.RGBDict[style])

????????self.workbook.save(self.excelFile)

??????except Exception as e:

????????raise e

????elif coordinate == None and rowNo is not None and \

????????????colsNo is not None:

??????try:

????????sheet.cell(row = rowNo,column = colsNo).value = content

????????if style:

??????????sheet.cell(row = rowNo,column = colsNo).\

????????????font = Font(color = self.RGBDict[style])

????????self.workbook.save(self.excelFile)

??????except Exception as e:

????????raise e

????else:

??????raise Exception("Insufficient Coordinates of cell !")

??def writeCellCurrentTime(self, sheet, coordinate = None,

????????rowNo = None, colsNo = None):

????# 寫入當(dāng)前的時(shí)間,下標(biāo)從1開(kāi)始

????now = int(time.time()) #顯示為時(shí)間戳

????timeArray = time.localtime(now)

????currentTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)

????if coordinate is not None:

??????try:

????????sheet.cell(coordinate = coordinate).value = currentTime

????????self.workbook.save(self.excelFile)

??????except Exception as e:

????????raise e

????elif coordinate == None and rowNo is not None \

????????and colsNo is not None:

??????try:

????????sheet.cell(row = rowNo, column = colsNo

????????????).value = currentTime

????????self.workbook.save(self.excelFile)

??????except Exception as e:

????????raise e

????else:

??????raise Exception("Insufficient Coordinates of cell !")

if __name__ == '__main__':

??# 測(cè)試代碼

??pe = ParseExcel()

??pe.loadWorkBook(r'D:\ProgramSourceCode\Python Source Code\WorkSpace\InterfaceFrame2018\inter_test_data.xlsx')

??sheetObj = pe.getSheetByName(u"API")

??print("通過(guò)名稱獲取sheet對(duì)象的名字:", sheetObj.title)

??# print help(sheetObj.rows)

??print("通過(guò)index序號(hào)獲取sheet對(duì)象的名字:", pe.getSheetByIndex(0).title)

??sheet = pe.getSheetByIndex(0)

??print(type(sheet))

??print(pe.getRowsNumber(sheet)) #獲取最大行號(hào)

??print(pe.getColsNumber(sheet)) #獲取最大列號(hào)

??rows = pe.getRow(sheet, 1) #獲取第一行

??for i in rows:

????print(i.value)

??# # 獲取第一行第一列單元格內(nèi)容

??# print pe.getCellOfValue(sheet, rowNo = 1, colsNo = 1)

??# pe.writeCell(sheet, u'我愛(ài)祖國(guó)', rowNo = 10, colsNo = 10)

??# pe.writeCellCurrentTime(sheet, rowNo = 10, colsNo = 11)

3.2 封裝get/post請(qǐng)求(HttpClient.py)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

import requests

import json

class HttpClient(object):

??def __init__(self):

????pass

??def request(self, requestMethod, requestUrl, paramsType,

????????requestData, headers =None, **kwargs):

????if requestMethod == "post":

??????print("---", requestData, type(requestData))

??????if paramsType == "form":

????????response = self.__post(url = requestUrl, data = json.dumps(eval(requestData)),

?????????????????headers = headers, **kwargs)

????????return response

??????elif paramsType == "json":

????????response = self.__post(url = requestUrl, json = json.dumps(eval(requestData)),

?????????????????headers = headers, **kwargs)

????????return response

????elif requestMethod == "get":

??????request_url = requestUrl

??????if paramsType == "url":

????????request_url = "%s%s" %(requestUrl, requestData)

??????response = self.__get(url = request_url, params = requestData, **kwargs)

??????return response

??def __post(self, url, data = None, json = None, headers=None,**kwargs):

????print("----")

????response = requests.post(url=url, data = data, json=json, headers=headers)

????return response

??def __get(self, url, params = None, **kwargs):

????response = requests.get(url, params = params, **kwargs)

????return response

if __name__ == "__main__":

??hc = HttpClient()

??res = hc.request("get", "http://39.106.41.11:8080/getBlogContent/", "url",'2')

??print(res.json())

3.3 封裝MD5(md5_encrypt)

1

2

3

4

5

6

7

8

9

10

import hashlib

def md5_encrypt(text):

??m5 = hashlib.md5()

??m5.update(text.encode("utf-8"))

??value = m5.hexdigest()

??return value

if __name__ == "__main__":

??print(md5_encrypt("sfwe"))

3.4 封裝Log

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

import logging

import logging.config

from config.public_data import baseDir

# 讀取日志配置文件

logging.config.fileConfig(baseDir + "\config\Logger.conf")

# 選擇一個(gè)日志格式

logger = logging.getLogger("example02")#或者example01

def debug(message):

??# 定義dubug級(jí)別日志打印方法

??logger.debug(message)

def info(message):

??# 定義info級(jí)別日志打印方法

??logger.info(message)

def warning(message):

??# 定義warning級(jí)別日志打印方法

??logger.warning(message)

3.5 封裝發(fā)送Email類

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

import smtplib

from email.mime.text import MIMEText

from email.mime.multipart import MIMEMultipart

from email.header import Header

from ProjVar.var import *

import os

import smtplib

from email import encoders

from email.mime.base import MIMEBase

from email.mime.text import MIMEText

from email.mime.multipart import MIMEMultipart

from email.header import Header

from email.utils import formataddr

def send_mail():

??mail_host="smtp.126.com" #設(shè)置服務(wù)器

??mail_user="testman1980"? #用戶名

??mail_pass="wulaoshi1980"? #口令

??sender = 'testman1980@126.com'

??receivers = ['2055739@qq.com',"testman1980@126.com"] # 接收郵件,可設(shè)置為你的QQ郵箱或者其他郵箱

??# 創(chuàng)建一個(gè)帶附件的實(shí)例

??message = MIMEMultipart()

??message['From'] = formataddr(["光榮之路吳老師", "testman1980@126.com"])

??message['To'] = ','.join(receivers)

??subject = '自動(dòng)化測(cè)試執(zhí)行報(bào)告'

??message['Subject'] = Header(subject, 'utf-8')

??message["Accept-Language"]="zh-CN"

??message["Accept-Charset"]="ISO-8859-1,utf-8,gbk"

??# 郵件正文內(nèi)容

??message.attach(MIMEText('最新執(zhí)行的自動(dòng)化測(cè)試報(bào)告,請(qǐng)參閱附件內(nèi)容!', 'plain', 'utf-8'))

??# 構(gòu)造附件1,傳送測(cè)試結(jié)果的excel文件

??att = MIMEBase('application', 'octet-stream')

??att.set_payload(open(ProjDirPath+"\\testdata\\testdata.xlsx", 'rb').read())

??att.add_header('Content-Disposition', 'attachment', filename=('gbk', '', "自動(dòng)化測(cè)試報(bào)告.xlsx"))

??encoders.encode_base64(att)

??message.attach(att)

??"""

??# 構(gòu)造附件2,傳送當(dāng)前目錄下的 runoob.txt 文件

??att2 = MIMEText(open('e:\\a.py','rb').read(), 'base64', 'utf-8')

??att2["Content-Type"] = 'application/octet-stream'

??att2["Content-Disposition"] = 'attachment; filename="a.py"'

??message.attach(att2)

??"""

??try:

????smtpObj = smtplib.SMTP(mail_host)

????smtpObj.login(mail_user, mail_pass)

????smtpObj.sendmail(sender, receivers, message.as_string())

????print("郵件發(fā)送成功")

??except smtplib.SMTPException as e:

????print("Error: 無(wú)法發(fā)送郵件", e)

if __name__ == "__main__":

??send_mail()

四、 創(chuàng)建config包 用來(lái)存放公共的參數(shù)、配置文件、長(zhǎng)時(shí)間不變的變量值

創(chuàng)建public_data.py

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

import os

# 整個(gè)項(xiàng)目的根目錄絕對(duì)路勁

baseDir = os.path.dirname(os.path.dirname(__file__))

# 獲取測(cè)試數(shù)據(jù)文件的絕對(duì)路徑

file_path = baseDir + "/TestData/inter_test_data.xlsx"

API_apiName = 2

API_requestUrl = 3

API_requestMothod = 4

API_paramsType = 5

API_apiTestCaseFileName = 6

API_active = 7

CASE_requestData = 1

CASE_relyData = 2

CASE_responseCode = 3

CASE_responseData = 4

CASE_dataStore = 5

CASE_checkPoint = 6

CASE_active = 7

CASE_status = 8

CASE_errorInfo = 9

# 存儲(chǔ)請(qǐng)求參數(shù)里面依賴的數(shù)據(jù)

REQUEST_DATA = {}

# 存儲(chǔ)響應(yīng)對(duì)象中的依賴數(shù)據(jù)

RESPONSE_DATA = {}

if __name__=="__main__":

??print(file_path)

??print(baseDir)

五、創(chuàng)建TestData目錄,用來(lái)存放測(cè)試文件

inter_test_data.xlsx

六、創(chuàng)建action包,用來(lái)存放關(guān)鍵字函數(shù)

6.1 解決數(shù)據(jù)依賴 (GetRely.py)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

from config.public_data import REQUEST_DATA, RESPONSE_DATA

from utils.md5_encrypt import md5_encrypt

REQUEST_DATA = {"用戶注冊(cè)":{"1":{"username":"zhangsan", "password":"dfsdf23"},

????????????"headers":{"cookie":"asdfwerw"}}}

RESPONSE_DATA = {"用戶注冊(cè)":{"1":{"code":"00"}, "headers":{"age":2342}}}

class GetRely(object):

??def __init__(self):

????pass

??@classmethod

??def get(self, dataSource, relyData, headSource = {}):

????print(type(dataSource))

????print(dataSource)

????data = dataSource.copy()

????for key, value in relyData.items():

??????if key == "request":

????????#說(shuō)明應(yīng)該去REQUEST_DATA中獲取

????????for k, v in value.items():

??????????interfaceName, case_idx = v.split("->")

??????????val = REQUEST_DATA[interfaceName][case_idx][k]

??????????if k == "password":

????????????data[k] = md5_encrypt(val)

??????????else:

????????????data[k] = val

??????elif key == "response":

????????# 應(yīng)該去RESPONSE_DATA中獲取

????????for k, v in value.items():

??????????interfaceName, case_idx = v.split("->")

??????????data[k] = RESPONSE_DATA[interfaceName][case_idx][k]

??????elif key == "headers":

????????if headSource:

??????????for key, value in value.items():

????????????if key == "request":

??????????????for k, v in value.items():

????????????????for i in v:

??????????????????headSource[i] = REQUEST_DATA[k]["headers"][i]

????????????elif key == "response":

??????????????for i, val in value.items():

????????????????for j in val:

??????????????????headSource[j] = RESPONSE_DATA[i]["headers"][j]

????return "%s" %data

if __name__ == "__main__":

??s = {"username": "", "password": "","code":""}

??h = {"cookie":"123", "age":332}

??rely = {"request": {"username": "用戶注冊(cè)->1", "password": "用戶注冊(cè)->1"},

??????"response":{"code":"用戶注冊(cè)->1"},

??????"headers":{"request":{"用戶注冊(cè)":["cookie"]},"response":{"用戶注冊(cè)":["age"]}}

??????}

??print(GetRely.get(s, rely, h))

6.2 解決數(shù)據(jù)存儲(chǔ)(RelyDataStore.py)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

from config.public_data import RESPONSE_DATA, REQUEST_DATA

class RelyDataStore(object):

??def __init__(self):

????pass

??@classmethod

??def do(cls, storePoint, apiName, caseId, request_source = {}, response_source = {}, req_headers={}, res_headers = {}):

????for key, value in storePoint.items():

??????if key == "request":

????????# 說(shuō)明需要存儲(chǔ)的依賴數(shù)據(jù)來(lái)自請(qǐng)求參數(shù),應(yīng)該將數(shù)據(jù)存儲(chǔ)到REQUEST_DATA

????????for i in value:

??????????if i in request_source:

????????????val = request_source[i]

????????????if apiName not in REQUEST_DATA:

??????????????# 說(shuō)明存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)還未生成,需要指明數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)

??????????????REQUEST_DATA[apiName]={str(caseId): {i: val}}

????????????else:

??????????????#說(shuō)明存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)中最外層結(jié)構(gòu)已存在

??????????????if str(caseId) in REQUEST_DATA[apiName]:

????????????????REQUEST_DATA[apiName][str(caseId)][i] = val

??????????????else:

????????????????# 說(shuō)明內(nèi)層結(jié)構(gòu)不完整,需要指明完整的結(jié)構(gòu)

????????????????REQUEST_DATA[apiName][str(caseId)] = {i: val}

??????????else:

????????????print("請(qǐng)求參數(shù)中不存在字段" + i)

??????elif key == "response":

????????#說(shuō)明需要存儲(chǔ)的依賴數(shù)據(jù)來(lái)自接口的響應(yīng)body,應(yīng)該將數(shù)據(jù)存儲(chǔ)到RESPONSE_DATA

????????for j in value:

??????????if j in response_source:

????????????val = response_source[j]

????????????if apiName not in RESPONSE_DATA:

??????????????# 說(shuō)明存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)還未生成,需要指明數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)

??????????????RESPONSE_DATA[apiName]={str(caseId): {j: val}}

????????????else:

??????????????#說(shuō)明存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)中最外層結(jié)構(gòu)已存在

??????????????if str(caseId) in RESPONSE_DATA[apiName]:

????????????????RESPONSE_DATA[apiName][str(caseId)][j] = val

??????????????else:

????????????????# 說(shuō)明內(nèi)層結(jié)構(gòu)不完整,需要指明完整的結(jié)構(gòu)

????????????????RESPONSE_DATA[apiName][str(caseId)] = {j: val}

??????????else:

????????????print("接口的響應(yīng)body中不存在字段" + j)

??????elif key == "headers":

????????for k, v in value.items():

??????????if k == "request":

????????????# 說(shuō)明需要往REQUEST_DATA變量中寫入存儲(chǔ)數(shù)據(jù)

????????????for item in v:

??????????????if item in req_headers:

????????????????header = req_headers[item]

????????????????if "headers" in REQUEST_DATA[apiName]:

??????????????????REQUEST_DATA[apiName]["headers"][item] = header

????????????????else:

??????????????????REQUEST_DATA[apiName]["headers"] = {item: header}

??????????elif k == "response":

????????????# 說(shuō)明需要往RESPONSE_DATA變量中寫入存儲(chǔ)數(shù)據(jù)

????????????for it in v:

??????????????if it in res_headers:

????????????????header = res_headers[it]

????????????????if "headers" in RESPONSE_DATA[apiName]:

??????????????????RESPONSE_DATA[apiName]["headers"][it] = header

????????????????else:

??????????????????RESPONSE_DATA[apiName]["headers"] = {item: header}

????print(REQUEST_DATA)

????print(RESPONSE_DATA)

if __name__ == "__main__":

??r = {"username": "srwcx01", "password": "wcx123wac1", "email": "wcx@qq.com"}

??req_h = {"cookie":"csdfw23"}

??res_h = {"age":597232}

??s = {"request": ["username", "password"], "response": ["userid"],"headers":{"request":["cookie"],

????"response":["age"]}}

??res = {"userid": 12, "code": "00"}

??RelyDataStore.do(s, "register", 1, r, res, req_headers=req_h, res_headers=res_h)

??print(REQUEST_DATA)

??print(RESPONSE_DATA)

6.3 校驗(yàn)數(shù)據(jù)結(jié)果(CheckResult.py)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

import re

class CheckResult(object):

??def __init__(self):

????pass

??@classmethod

??def check(self, responseObj, checkPoint):

????responseBody = responseObj.json()

????# responseBody = {"code": "", "userid": 12, "id": "12"}

????errorKey = {}

????for key, value in checkPoint.items():

??????if key in responseBody:

????????if isinstance(value, (str, int)):

??????????# 等值校驗(yàn)

??????????if responseBody[key] != value:

????????????errorKey[key] = responseBody[key]

????????elif isinstance(value, dict):

??????????sourceData = responseBody[key]

??????????if "value" in value:

????????????# 模糊匹配校驗(yàn)

????????????regStr = value["value"]

????????????rg = re.match(regStr, "%s" %sourceData)

????????????if not rg:

??????????????errorKey[key] = sourceData

??????????elif "type" in value:

????????????# 數(shù)據(jù)類型校驗(yàn)

????????????typeS = value["type"]

????????????if typeS == "N":

??????????????# 說(shuō)明是整形校驗(yàn)

??????????????if not isinstance(sourceData, int):

????????????????errorKey[key] = sourceData

??????else:

????????errorKey[key] = "[%s] not exist" %key

????return errorKey

if __name__ == "__main__":

??r = {"code": "00", "userid": 12, "id": 12}

??c = {"code": "00", "userid": {"type": "N"}, "id": {"value": "\d+"}}

??print(CheckResult.check(r, c))

6.4 往excel里面寫結(jié)果

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

from config.public_data import *

def write_result(wbObj, sheetObj, responseData, errorKey, rowNum):

??try:

????# 寫響應(yīng)body

????wbObj.writeCell(sheetObj, content="%s" %responseData,

????????????rowNo = rowNum, colsNo=CASE_responseData)

????# 寫校驗(yàn)結(jié)果狀態(tài)及錯(cuò)誤信息

????if errorKey:

??????wbObj.writeCell(sheetObj, content="%s" %errorKey,

????????????rowNo=rowNum, colsNo=CASE_errorInfo)

??????wbObj.writeCell(sheetObj, content="faild",

??????????????rowNo=rowNum, colsNo=CASE_status, style="red")

????else:

??????wbObj.writeCell(sheetObj, content="pass",

??????????????rowNo=rowNum, colsNo=CASE_status, style="green")

??except Exception as err:

????raise err

七、創(chuàng)建Log目錄用來(lái)存放日志

八、主函數(shù)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

#encoding=utf-8

import requests

import json

from action.get_rely import GetRely

from config.public_data import *

from utils.ParseExcel import ParseExcel

from utils.HttpClient import HttpClient

from action.data_store import RelyDataStore

from action.check_result import CheckResult

from action.write_result import write_result

from utils.Log import *

def main():

??parseE = ParseExcel()

??parseE.loadWorkBook(file_path)

??sheetObj = parseE.getSheetByName("API")

??activeList = parseE.getColumn(sheetObj, API_active)

??for idx, cell in enumerate(activeList[1:], 2):

????if cell.value == "y":

??????#需要被執(zhí)行

??????RowObj = parseE.getRow(sheetObj, idx)

??????apiName = RowObj[API_apiName -1].value

??????requestUrl = RowObj[API_requestUrl - 1].value

??????requestMethod = RowObj[API_requestMothod - 1].value

??????paramsType = RowObj[API_paramsType - 1].value

??????apiTestCaseFileName = RowObj[API_apiTestCaseFileName - 1].value

??????# 下一步讀取用例sheet表,準(zhǔn)備執(zhí)行測(cè)試用例

??????caseSheetObj = parseE.getSheetByName(apiTestCaseFileName)

??????caseActiveObj = parseE.getColumn(caseSheetObj, CASE_active)

??????for c_idx, col in enumerate(caseActiveObj[1:], 2):

????????if col.value == "y":

??????????#需要執(zhí)行的用例

??????????caseRowObj = parseE.getRow(caseSheetObj, c_idx)

??????????requestData = caseRowObj[CASE_requestData - 1].value

??????????relyData = caseRowObj[CASE_relyData - 1].value

??????????responseCode = caseRowObj[CASE_responseCode - 1].value

??????????responseData = caseRowObj[CASE_responseData - 1].value

??????????dataStore = caseRowObj[CASE_dataStore -1].value

??????????checkPoint = caseRowObj[CASE_checkPoint - 1].value

??????????#發(fā)送接口請(qǐng)求之前需要做一下數(shù)據(jù)依賴的處理

??????????if relyData:

????????????logging.info("處理第%s個(gè)接口的第%s條用例的數(shù)據(jù)依賴!")

????????????requestData = GetRely.get(eval(requestData), eval(relyData))

??????????httpC = HttpClient()

??????????response = httpC.request(requestMethod=requestMethod,

???????????????????????requestData=requestData,

???????????????????????requestUrl=requestUrl,

???????????????????????paramsType=paramsType

???????????????????????)

??????????# 獲取到響應(yīng)結(jié)果后,接下來(lái)進(jìn)行數(shù)據(jù)依賴存儲(chǔ)邏輯實(shí)現(xiàn)

??????????if response.status_code == 200:

????????????responseData = response.json()

????????????# 進(jìn)行依賴數(shù)據(jù)存儲(chǔ)

????????????if dataStore:

??????????????RelyDataStore.do(eval(dataStore), apiName, c_idx - 1, eval(requestData), responseData)

????????????# 接下來(lái)就是校驗(yàn)結(jié)果

????????????else:

??????????????logging.info("接口【%s】的第【%s】條用例,不需要進(jìn)行依賴數(shù)據(jù)存儲(chǔ)!" %(apiName, c_idx))

????????????if checkPoint:

??????????????errorKey = CheckResult.check(response, eval(checkPoint))

??????????????write_result(parseE, caseSheetObj, responseData, errorKey, c_idx)

??????????else:

????????????logging.info("接口【%s】的第【%s】條用例,執(zhí)行失敗,接口協(xié)議code非200!" %(apiName, c_idx))

????????else:

??????????logging.info("第%s個(gè)接口的第%s條用例,被忽略執(zhí)行!" %(idx -1, c_idx-1))

????else:

??????logging.info("第%s行的接口被忽略執(zhí)行!" %(idx -1))

if __name__=="__main__":

??main()

?現(xiàn)在我也找了很多測(cè)試的朋友,做了一個(gè)分享技術(shù)的交流群,共享了很多我們收集的技術(shù)文檔和視頻教程。
如果你不想再體驗(yàn)自學(xué)時(shí)找不到資源,沒(méi)人解答問(wèn)題,堅(jiān)持幾天便放棄的感受
可以加入我們一起交流。而且還有很多在自動(dòng)化,性能,安全,測(cè)試開(kāi)發(fā)等等方面有一定建樹(shù)的技術(shù)大牛
分享他們的經(jīng)驗(yàn),還會(huì)分享很多直播講座和技術(shù)沙龍
可以免費(fèi)學(xué)習(xí)!劃重點(diǎn)!開(kāi)源的?。。?qq群號(hào):485187702【暗號(hào):csdn11】

最后感謝每一個(gè)認(rèn)真閱讀我文章的人,看著粉絲一路的上漲和關(guān)注,禮尚往來(lái)總是要有的,雖然不是什么很值錢的東西,如果你用得到的話可以直接拿走!?希望能幫助到你!【100%無(wú)套路免費(fèi)領(lǐng)取】

python+requests接口自動(dòng)化框架的實(shí)現(xiàn),python,軟件測(cè)試,程序員,接口測(cè)試,自動(dòng)化測(cè)試,測(cè)試工程師

python+requests接口自動(dòng)化框架的實(shí)現(xiàn),python,軟件測(cè)試,程序員,接口測(cè)試,自動(dòng)化測(cè)試,測(cè)試工程師文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-839089.html

到了這里,關(guān)于python+requests接口自動(dòng)化框架的實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 一個(gè)簡(jiǎn)單的接口自動(dòng)化測(cè)試框架:Python+Requests+Pytest+Allure

    一個(gè)簡(jiǎn)單的接口自動(dòng)化測(cè)試框架:Python+Requests+Pytest+Allure

    project:api_test ——api_keyword ————api_key.py:接口驅(qū)動(dòng)類 ——case ————test_cases.py:測(cè)試套件和測(cè)試用例 ——report_allure( 無(wú)需創(chuàng)建 ):allure報(bào)告 ——result( 無(wú)需創(chuàng)建 ):測(cè)試用例運(yùn)行結(jié)果 ——VAR ————VAR.py:常量類 conftest.py:項(xiàng)目級(jí)別fixture main.py:主函數(shù)

    2024年02月03日
    瀏覽(95)
  • (Python)Requests+Pytest+Allure接口自動(dòng)化測(cè)試框架從0到1搭建

    (Python)Requests+Pytest+Allure接口自動(dòng)化測(cè)試框架從0到1搭建

    前面,已經(jīng)學(xué)習(xí)了如何用SpringBoot寫接口以及與Mysql數(shù)據(jù)庫(kù)進(jìn)行交互,具體可查閱下面的這篇博客,今天學(xué)習(xí)一下基于Python的接口自動(dòng)化測(cè)試框架的搭建,主要包括以下內(nèi)容:利用request庫(kù)發(fā)送請(qǐng)求,請(qǐng)求數(shù)據(jù)參數(shù)化處理,還涉及到數(shù)據(jù)庫(kù)(Mysql+MongDB)方面的交互,包括如何取數(shù)

    2024年02月13日
    瀏覽(722)
  • Python+Requests實(shí)現(xiàn)接口自動(dòng)化測(cè)試

    Python+Requests實(shí)現(xiàn)接口自動(dòng)化測(cè)試

    一般對(duì)于自動(dòng)化的理解,有兩種方式的自動(dòng)化。 第一,不需要寫代碼,完全由工具實(shí)現(xiàn),這種方式的工具一般是公司自己研發(fā)的,方便黑盒測(cè)試人員使用。這種工具的特點(diǎn)是學(xué)習(xí)成本低,方便使用,但是通用性不強(qiáng),也就是換了一家公司,就很有可能無(wú)法使用之前的工具。

    2024年01月16日
    瀏覽(22)
  • Python+Requests+Pytest+Excel+Allure 接口自動(dòng)化測(cè)試項(xiàng)目實(shí)戰(zhàn)【框架之間的對(duì)比】

    Python+Requests+Pytest+Excel+Allure 接口自動(dòng)化測(cè)試項(xiàng)目實(shí)戰(zhàn)【框架之間的對(duì)比】

    ? ? ? ? --------UnitTest框架和PyTest框架的簡(jiǎn)單認(rèn)識(shí)對(duì)比與項(xiàng)目實(shí)戰(zhàn)-------- 定義: Unittest是Python標(biāo)準(zhǔn)庫(kù)中自帶的單元測(cè)試框架,Unittest有時(shí)候也被稱為PyUnit,就像JUnit是Java語(yǔ)言的標(biāo)準(zhǔn)單元測(cè)試框架一樣,Unittest則是Python語(yǔ)言的標(biāo)準(zhǔn)單元測(cè)試框架。 Pytest是Python的另一個(gè)第三方單元測(cè)

    2024年02月09日
    瀏覽(94)
  • Python+Requests+Pytest+YAML+Allure實(shí)現(xiàn)接口自動(dòng)化

    Python+Requests+Pytest+YAML+Allure實(shí)現(xiàn)接口自動(dòng)化

    本項(xiàng)目實(shí)現(xiàn)接口自動(dòng)化的技術(shù)選型:Python+Requests+Pytest+YAML+Allure ,主要是針對(duì)之前開(kāi)發(fā)的一個(gè)接口項(xiàng)目來(lái)進(jìn)行學(xué)習(xí),通過(guò) Python+Requests 來(lái)發(fā)送和處理HTTP協(xié)議的請(qǐng)求接口,使用 Pytest 作為測(cè)試執(zhí)行器,使用 YAML 來(lái)管理測(cè)試數(shù)據(jù),使用 Allure 來(lái)生成測(cè)試報(bào)告 本項(xiàng)目在實(shí)現(xiàn)過(guò)程中,把

    2024年02月11日
    瀏覽(791)
  • 接口自動(dòng)化框架(Pytest+request+Allure)

    接口自動(dòng)化框架(Pytest+request+Allure)

    接口自動(dòng)化是指模擬程序接口層面的自動(dòng)化,由于接口不易變更,維護(hù)成本更小,所以深受各大公司的喜愛(ài)。 接口自動(dòng)化包含2個(gè)部分,功能性的接口自動(dòng)化測(cè)試和并發(fā)接口自動(dòng)化測(cè)試。 本次文章著重介紹第一種,功能性的接口自動(dòng)化框架。 環(huán)境:Mac、Python 3,Pytest,Allure,

    2024年03月14日
    瀏覽(233)
  • 接口自動(dòng)化測(cè)試:Requests統(tǒng)一請(qǐng)求封裝(框架的封裝)

    一、為什么要做統(tǒng)一請(qǐng)求封裝? 1. 去除很多重復(fù)的、冗余的代碼; 2.? 異常處理和日志監(jiān)控: 設(shè)置統(tǒng)一的公共參數(shù)、統(tǒng)一的文件處理、統(tǒng)一的異常處理、統(tǒng)一的日志監(jiān)控、統(tǒng)一的用例斷言等; 3. 跨py文件實(shí)現(xiàn)通過(guò)一個(gè)session自動(dòng)管理有cookie關(guān)聯(lián)的接口; ??????????????

    2024年01月24日
    瀏覽(26)
  • pytest+requests+Python3.7+yaml+Allure+Jenkins+docker實(shí)現(xiàn)接口自動(dòng)化

    pytest+requests+Python3.7+yaml+Allure+Jenkins+docker實(shí)現(xiàn)接口自動(dòng)化

    目錄 接口自動(dòng)化測(cè)試框架(用例自動(dòng)生成) 項(xiàng)目說(shuō)明 技術(shù)棧 環(huán)境部署 框架流程圖與目錄結(jié)構(gòu)圖及相關(guān)說(shuō)明 1、框架流程圖如下 2、代碼目錄結(jié)構(gòu)圖如下 關(guān)聯(lián)詳解 函數(shù)助手詳解 代碼設(shè)計(jì)與功能說(shuō)明 1、定義運(yùn)行配置文件 runConfig.yml 2、接口配置文件 apiConfig.ini 3、測(cè)試用例的設(shè)

    2024年02月09日
    瀏覽(699)
  • Python接口自動(dòng)化之request請(qǐng)求封裝

    Python接口自動(dòng)化之request請(qǐng)求封裝

    我們?cè)谧鲎詣?dòng)化測(cè)試的時(shí)候,大家都是希望自己寫的代碼越簡(jiǎn)潔越好,代碼重復(fù)量越少越好。那么,我們可以考慮將request的請(qǐng)求類型(如:Get、Post、Delect請(qǐng)求)都封裝起來(lái)。這樣,我們?cè)诰帉懹美臅r(shí)候就可以直接進(jìn)行請(qǐng)求了。 我們先來(lái)看一下Get、Post、Delect等請(qǐng)求的源碼,

    2024年02月13日
    瀏覽(22)
  • Python接口自動(dòng)化搭建過(guò)程,含request請(qǐng)求封裝

    Python接口自動(dòng)化搭建過(guò)程,含request請(qǐng)求封裝

    接口測(cè)試自動(dòng)化好處 顯而易見(jiàn)的好處就是解放雙手??。 可以在短時(shí)間內(nèi)自動(dòng)執(zhí)行大量的測(cè)試用例 通過(guò)參數(shù)化和數(shù)據(jù)驅(qū)動(dòng)的方式進(jìn)行測(cè)試數(shù)據(jù)的變化,提高測(cè)試覆蓋范圍 快速反饋測(cè)試執(zhí)行結(jié)果和報(bào)告 支持持續(xù)集成和持續(xù)交付的流程 使用Requests+pytest+allure搭建測(cè)試框架的目的

    2024年02月07日
    瀏覽(31)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包