本文實例講述了python http接口自動化測試框架實現(xiàn)方法。分享給大家供大家參考,具體如下:
一、測試需求描述
對服務后臺一系列的http接口功能測試。
輸入:根據(jù)接口描述構造不同的參數(shù)輸入值
輸出:xml文件
eg:http://xxx.com/xxx_product/test/content_book_list.jsp?listid=1
二、實現(xiàn)方法
1、選用python腳本來驅動測試
2、采用excel表格管理測試數(shù)據(jù),包括用例的管理、測試數(shù)據(jù)錄入、測試結果顯示等等,這個需要封裝一個excel的類即可。
3、調用http接口采用python封裝好的api即可
4、測試需要的http組裝字符轉處理即可
5、設置2個檢查點,xml文件中的返回值字段(通過解析xml得到);xml文件的正確性(文件對比)
6、首次執(zhí)行測試采用半自動化的方式,即人工檢查輸出的xml文件是否正確,一旦正確將封存xml文件,為后續(xù)回歸測試的預期結果,如果發(fā)現(xiàn)錯誤手工修正為預期文件。(注意不是每次測試都人工檢查該文件,只首次測試的時候才檢查)
三、excel表格樣式
四、實現(xiàn)代碼(代碼才是王道,有注釋很容易就能看明白的)
1、測試框架代碼
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
|
#**************************************************************** # testframe.py # author : vince # version : 1.1.2 # date : 2011-3-14 # description: 自動化測試平臺 #**************************************************************** import os,sys, urllib, httplib, profile, datetime, time from xml2dict import xml2dict import win32com.client from win32com.client import dispatch import xml.etree.elementtree as et #import mysqldb #excel表格中測試結果底色 ok_color = 0xffffff ng_color = 0xff #nt_color=0xffff nt_color = 0xc0c0c0 #excel表格中測試結果匯總顯示位置 testtime = [ 1 , 14 ] testresult = [ 2 , 14 ] #excel模版設置 #self.titleindex=3 #excel中測試用例標題行索引 #self.casebegin =4 #excel中測試用例開始行索引 #self.argbegin =3 #excel中參數(shù)開始列索引 #self.argcount =8 #excel中支持的參數(shù)個數(shù) class create_excel: def __init__( self , sfile, dtitleindex = 3 , dcasebegin = 4 , dargbegin = 3 , dargcount = 8 ): self .xlapp = win32com.client.dispatch( 'et.application' ) #ms:excel wps:et try : self .book = self .xlapp.workbooks. open (sfile) except : print_error_info() print "打開文件失敗" exit() self . file = sfile self .titleindex = dtitleindex self .casebegin = dcasebegin self .argbegin = dargbegin self .argcount = dargcount self .allresult = [] self .retcol = self .argbegin + self .argcount self .xmlcol = self .retcol + 1 self .resultcol = self .xmlcol + 1 def close( self ): #self.book.close(savechanges=0) self .book.save() self .book.close() #self.xlapp.quit() del self .xlapp def read_data( self , isheet, irow, icol): try : sht = self .book.worksheets(isheet) svalue = str (sht.cells(irow, icol).value) except : self .close() print ( '讀取數(shù)據(jù)失敗' ) exit() #去除'.0' if svalue[ - 2 :] = = '.0' : svalue = svalue[ 0 : - 2 ] return svalue def write_data( self , isheet, irow, icol, sdata, color = ok_color): try : sht = self .book.worksheets(isheet) sht.cells(irow, icol).value = sdata.decode( "utf-8" ) sht.cells(irow, icol).interior.color = color self .book.save() except : self .close() print ( '寫入數(shù)據(jù)失敗' ) exit() #獲取用例個數(shù) def get_ncase( self , isheet): try : return self .get_nrows(isheet) - self .casebegin + 1 except : self .close() print ( '獲取case個數(shù)失敗' ) exit() def get_nrows( self , isheet): try : sht = self .book.worksheets(isheet) return sht.usedrange.rows.count except : self .close() print ( '獲取nrows失敗' ) exit() def get_ncols( self , isheet): try : sht = self .book.worksheets(isheet) return sht.usedrange.columns.count except : self .close() print ( '獲取ncols失敗' ) exit() def del_testrecord( self , suiteid): try : #為提升性能特別從for循環(huán)提取出來 nrows = self .get_nrows(suiteid) + 1 ncols = self .get_ncols(suiteid) + 1 begincol = self .argbegin + self .argcount #提升性能 sht = self .book.worksheets(suiteid) for row in range ( self .casebegin, nrows): for col in range (begincol, ncols): str = self .read_data(suiteid, row, col) #清除實際結果[] startpos = str .find( '[' ) if startpos> 0 : str = str [ 0 :startpos].strip() self .write_data(suiteid, row, col, str , ok_color) else : #提升性能 sht.cells(row, col).interior.color = ok_color #清除testresul列中的測試結果,設置為nt self .write_data(suiteid, row, self .argbegin + self .argcount + 1 , ' ' , ok_color) self .write_data(suiteid, row, self .resultcol, 'nt' , nt_color) except : self .close() print ( '清除數(shù)據(jù)失敗' ) exit() #執(zhí)行調用 def httpinvoke(ipport, url): conn = httplib.httpconnection(ipport) conn.request( "get" , url) rsps = conn.getresponse() data = rsps.read() conn.close() return data #獲取用例基本信息[interface,argcount,[argnamelist]] def get_caseinfo(data, suiteid): caseinfolist = [] sinterface = data.read_data(suiteid, 1 , 2 ) argcount = int (data.read_data(suiteid, 2 , 2 )) #獲取參數(shù)名存入argnamelist argnamelist = [] for i in range ( 0 , argcount): argnamelist.append(data.read_data(suiteid, data.titleindex, data.argbegin + i)) caseinfolist.append(sinterface) caseinfolist.append(argcount) caseinfolist.append(argnamelist) return caseinfolist #獲取輸入 def get_input(data, suiteid, caseid, caseinfolist): sarge = '' #參數(shù)組合 for j in range ( 0 , caseinfolist[ 1 ]): if data.read_data(suiteid, data.casebegin + caseid, data.argbegin + j) ! = "none" : sarge = sarge + caseinfolist[ 2 ][j] + '=' + data.read_data(suiteid, data.casebegin + caseid, data.argbegin + j) + '&' #去掉結尾的&字符 if sarge[ - 1 :] = = '&' : sarge = sarge[ 0 : - 1 ] sinput = caseinfolist[ 0 ] + sarge #組合全部參數(shù) return sinput #結果判斷 def assert_result(sreal, sexpect): sreal = str (sreal) sexpect = str (sexpect) if sreal = = sexpect: return 'ok' else : return 'ng' #將測試結果寫入文件 def write_result(data, suiteid, caseid, resultcol, * result): if len (result)> 1 : ret = 'ok' for i in range ( 0 , len (result)): if result[i] = = 'ng' : ret = 'ng' break if ret = = 'ng' : data.write_data(suiteid, data.casebegin + caseid, resultcol,ret, ng_color) else : data.write_data(suiteid, data.casebegin + caseid, resultcol,ret, ok_color) data.allresult.append(ret) else : if result[ 0 ] = = 'ng' : data.write_data(suiteid, data.casebegin + caseid, resultcol,result[ 0 ], ng_color) elif result[ 0 ] = = 'ok' : data.write_data(suiteid, data.casebegin + caseid, resultcol,result[ 0 ], ok_color) else : #nt data.write_data(suiteid, data.casebegin + caseid, resultcol,result[ 0 ], nt_color) data.allresult.append(result[ 0 ]) #將當前結果立即打印 print 'case' + str (caseid + 1 ) + ':' , data.allresult[ - 1 ] #打印測試結果 def statisticresult(excelobj): allresultlist = excelobj.allresult count = [ 0 , 0 , 0 ] for i in range ( 0 , len (allresultlist)): #print 'case'+str(i+1)+':', allresultlist[i] count = countflag(allresultlist[i],count[ 0 ], count[ 1 ], count[ 2 ]) print 'statistic result as follow:' print 'ok:' , count[ 0 ] print 'ng:' , count[ 1 ] print 'nt:' , count[ 2 ] #解析xmlstring返回dict def get_xmlstring_dict(xml_string): xml = xml2dict() return xml.fromstring(xml_string) #解析xmlfile返回dict def get_xmlfile_dict(xml_file): xml = xml2dict() return xml.parse(xml_file) #去除歷史數(shù)據(jù)expect[real] def delcomment(excelobj, suiteid, irow, icol, str ): startpos = str .find( '[' ) if startpos> 0 : str = str [ 0 :startpos].strip() excelobj.write_data(suiteid, irow, icol, str , ok_color) return str #檢查每個item (非結構體) def check_item(excelobj, suiteid, caseid,real_dict, checklist, begincol): ret = 'ok' for checkid in range ( 0 , len (checklist)): real = real_dict[checklist[checkid]][ 'value' ] expect = excelobj.read_data(suiteid, excelobj.casebegin + caseid, begincol + checkid) #如果檢查不一致測將實際結果寫入expect字段,格式:expect[real] #將return ng result = assert_result(real, expect) if result = = 'ng' : writestr = expect + '[' + real + ']' excelobj.write_data(suiteid, excelobj.casebegin + caseid, begincol + checkid, writestr, ng_color) ret = 'ng' return ret #檢查結構體類型 def check_struct_item(excelobj, suiteid, caseid,real_struct_dict, structlist, structbegin, structcount): ret = 'ok' if structcount> 1 : #傳入的是list for structid in range ( 0 , structcount): structdict = real_struct_dict[structid] temp = check_item(excelobj, suiteid, caseid,structdict, structlist, structbegin + structid * len (structlist)) if temp = = 'ng' : ret = 'ng' else : #傳入的是dict temp = check_item(excelobj, suiteid, caseid,real_struct_dict, structlist, structbegin) if temp = = 'ng' : ret = 'ng' return ret #獲取異常函數(shù)及行號 def print_error_info(): """return the frame object for the caller's stack frame.""" try : raise exception except : f = sys.exc_info()[ 2 ].tb_frame.f_back print (f.f_code.co_name, f.f_lineno) #測試結果計數(shù)器,類似switch語句實現(xiàn) def countflag(flag,ok, ng, nt): calculation = { 'ok' : lambda :[ok + 1 , ng, nt], 'ng' : lambda :[ok, ng + 1 , nt], 'nt' : lambda :[ok, ng, nt + 1 ]} return calculation[flag]() |
2、項目測試代碼
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
|
# -*- coding: utf-8 -*- #**************************************************************** # xxx_server_case.py # author : vince # version : 1.0 # date : 2011-3-10 # description: 內容服務系統(tǒng)測試代碼 #**************************************************************** from testframe import * from common_lib import * httpstring = 'http://xxx.com/xxx_product/test/' expectxmldir = os.getcwd() + '/testdir/expect/' realxmldir = os.getcwd() + '/testdir/real/' def run(interface_name, suiteid): print '【' + interface_name + '】' + ' test begin,please waiting...' global expectxmldir, realxmldir #根據(jù)接口名分別創(chuàng)建預期結果目錄和實際結果目錄 expectdir = expectxmldir + interface_name realdir = realxmldir + interface_name if os.path.exists(expectdir) = = 0 : os.makedirs(expectdir) if os.path.exists(realdir) = = 0 : os.makedirs(realdir) excelobj.del_testrecord(suiteid) #清除歷史測試數(shù)據(jù) casecount = excelobj.get_ncase(suiteid) #獲取case個數(shù) caseinfolist = get_caseinfo(excelobj, suiteid) #獲取case基本信息 #遍歷執(zhí)行case for caseid in range ( 0 , casecount): #檢查是否執(zhí)行該case if excelobj.read_data(suiteid,excelobj.casebegin + caseid, 2 ) = = 'n' : write_result(excelobj, suiteid, caseid, excelobj.resultcol, 'nt' ) continue #當前case結束,繼續(xù)執(zhí)行下一個case #獲取測試數(shù)據(jù) sinput = httpstring + get_input(excelobj, suiteid, caseid, caseinfolist) xmlstring = httpinvoke(com_ipport, sinput) #執(zhí)行調用 #獲取返回碼并比較 result_code = et.fromstring(xmlstring).find( "result_code" ).text ret1 = check_result(excelobj, suiteid, caseid,result_code, excelobj.retcol) #保存預期結果文件 expectpath = expectdir + '/' + str (caseid + 1 ) + '.xml' #savexmlfile(expectpath, xmlstring) #保存實際結果文件 realpath = realdir + '/' + str (caseid + 1 ) + '.xml' savexmlfile(realpath, xmlstring) #比較預期結果和實際結果 ret2 = check_xmlfile(excelobj, suiteid, caseid,expectpath, realpath) #寫測試結果 write_result(excelobj, suiteid, caseid, excelobj.resultcol, ret1, ret2) print '【' + interface_name + '】' + ' test end!' |
3、測試入口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# -*- coding: utf-8 -*- #**************************************************************** # main.py # author : vince # version : 1.0 # date : 2011-3-16 # description: 測試組裝,用例執(zhí)行入口 #**************************************************************** from testframe import * from xxx_server_case import * import xxx_server_case #產(chǎn)品系統(tǒng)接口測試 #設置測試環(huán)境 xxx_server_case.excelobj = create_excel(os.getcwd() + '/testdir/xxx_testcase.xls' ) xxx_server_case.com_ipport = xxx.com' #add testsuite begin run( "xxx_book_list" , 4 ) #add other suite from here #add testsuite end statisticresult(xxx_server_case.excelobj) xxx_server_case.excelobj.close() |
希望本文所述對大家python程序設計有所幫助。
原文鏈接:https://blog.csdn.net/qq_24373725/article/details/77992656