一、测试需求描述

对服务后台一系列的http接口功能测试。

输入:根据接口描述构造不同的参数输入值

输出:XML文件

eg:http://xxx.com/xxx_product/test/content_book_list.jsp?listid=1

二、实现方法

1、选用Python脚本来驱动测试

2、采用Excel表格管理测试数据,包括用例的管理、测试数据录入、测试结果显示等等,这个需要封装一个Excel的类即可。

3、调用http接口采用Python封装好的API即可

4、测试需要的http组装字符转处理即可

5、设置2个检查点,XML文件中的返回值字段(通过解析XML得到);XML文件的正确性(文件对比)

6、首次执行测试采用半自动化的方式,即人工检查输出的XML文件是否正确,一旦正确将封存XML文件,为后续回归测试的预期结果,如果发现错误手工修正为预期文件。(注意不是每次测试都人工检查该文件,只首次测试的时候才检查)

三、Excel表格样式

四、实现代码(代码才是王道,有注释很容易就能看明白的)

1、测试框架代码

  1. #****************************************************************
  2. # TestFrame.py
  3. # Author     : Vince
  4. # Version    : 1.1.2
  5. # Date       : 2011-3-14
  6. # Description: 自动化测试平台
  7. #****************************************************************
  8. import os,sys, urllib, httplib, profile, datetime, time
  9. from xml2dict import XML2Dict
  10. import win32com.client
  11. from win32com.client import Dispatch
  12. import xml.etree.ElementTree as et
  13. #import MySQLdb
  14. #Excel表格中测试结果底色
  15. OK_COLOR=0xffffff
  16. NG_COLOR=0xff
  17. #NT_COLOR=0xffff
  18. NT_COLOR=0xC0C0C0
  19. #Excel表格中测试结果汇总显示位置
  20. TESTTIME=[1, 14]
  21. TESTRESULT=[2, 14]
  22. #Excel模版设置
  23. #self.titleindex=3        #Excel中测试用例标题行索引
  24. #self.casebegin =4        #Excel中测试用例开始行索引
  25. #self.argbegin   =3       #Excel中参数开始列索引
  26. #self.argcount  =8        #Excel中支持的参数个数
  27. class create_excel:
  28. def __init__(self, sFile, dtitleindex=3, dcasebegin=4, dargbegin=3, dargcount=8):
  29. self.xlApp = win32com.client.Dispatch('et.Application')   #MS:Excel  WPS:et
  30. try:
  31. self.book = self.xlApp.Workbooks.Open(sFile)
  32. except:
  33. print_error_info()
  34. print "打开文件失败"
  35. exit()
  36. self.file=sFile
  37. self.titleindex=dtitleindex
  38. self.casebegin=dcasebegin
  39. self.argbegin=dargbegin
  40. self.argcount=dargcount
  41. self.allresult=[]
  42. self.retCol=self.argbegin+self.argcount
  43. self.xmlCol=self.retCol+1
  44. self.resultCol=self.xmlCol+1
  45. def close(self):
  46. #self.book.Close(SaveChanges=0)
  47. self.book.Save()
  48. self.book.Close()
  49. #self.xlApp.Quit()
  50. del self.xlApp
  51. def read_data(self, iSheet, iRow, iCol):
  52. try:
  53. sht = self.book.Worksheets(iSheet)
  54. sValue=str(sht.Cells(iRow, iCol).Value)
  55. except:
  56. self.close()
  57. print('读取数据失败')
  58. exit()
  59. #去除'.0'
  60. if sValue[-2:]=='.0':
  61. sValue = sValue[0:-2]
  62. return sValue
  63. def write_data(self, iSheet, iRow, iCol, sData, color=OK_COLOR):
  64. try:
  65. sht = self.book.Worksheets(iSheet)
  66. sht.Cells(iRow, iCol).Value = sData.decode("utf-8")
  67. sht.Cells(iRow, iCol).Interior.Color=color
  68. self.book.Save()
  69. except:
  70. self.close()
  71. print('写入数据失败')
  72. exit()
  73. #获取用例个数
  74. def get_ncase(self, iSheet):
  75. try:
  76. return self.get_nrows(iSheet)-self.casebegin+1
  77. except:
  78. self.close()
  79. print('获取Case个数失败')
  80. exit()
  81. def get_nrows(self, iSheet):
  82. try:
  83. sht = self.book.Worksheets(iSheet)
  84. return sht.UsedRange.Rows.Count
  85. except:
  86. self.close()
  87. print('获取nrows失败')
  88. exit()
  89. def get_ncols(self, iSheet):
  90. try:
  91. sht = self.book.Worksheets(iSheet)
  92. return sht.UsedRange.Columns.Count
  93. except:
  94. self.close()
  95. print('获取ncols失败')
  96. exit()
  97. def del_testrecord(self, suiteid):
  98. try:
  99. #为提升性能特别从For循环提取出来
  100. nrows=self.get_nrows(suiteid)+1
  101. ncols=self.get_ncols(suiteid)+1
  102. begincol=self.argbegin+self.argcount
  103. #提升性能
  104. sht = self.book.Worksheets(suiteid)
  105. for row in range(self.casebegin, nrows):
  106. for col in range(begincol, ncols):
  107. str=self.read_data(suiteid, row, col)
  108. #清除实际结果[]
  109. startpos = str.find('[')
  110. if startpos>0:
  111. str = str[0:startpos].strip()
  112. self.write_data(suiteid, row, col, str, OK_COLOR)
  113. else:
  114. #提升性能
  115. sht.Cells(row, col).Interior.Color = OK_COLOR
  116. #清除TestResul列中的测试结果,设置为NT
  117. self.write_data(suiteid, row,  self.argbegin+self.argcount+1, ' ', OK_COLOR)
  118. self.write_data(suiteid, row, self.resultCol, 'NT', NT_COLOR)
  119. except:
  120. self.close()
  121. print('清除数据失败')
  122. exit()
  123. #执行调用
  124. def HTTPInvoke(IPPort, url):
  125. conn = httplib.HTTPConnection(IPPort)
  126. conn.request("GET", url)
  127. rsps = conn.getresponse()
  128. data = rsps.read()
  129. conn.close()
  130. return data
  131. #获取用例基本信息[Interface,argcount,[ArgNameList]]
  132. def get_caseinfo(Data, SuiteID):
  133. caseinfolist=[]
  134. sInterface=Data.read_data(SuiteID, 1, 2)
  135. argcount=int(Data.read_data(SuiteID, 2, 2))
  136. #获取参数名存入ArgNameList
  137. ArgNameList=[]
  138. for i in range(0, argcount):
  139. ArgNameList.append(Data.read_data(SuiteID, Data.titleindex, Data.argbegin+i))
  140. caseinfolist.append(sInterface)
  141. caseinfolist.append(argcount)
  142. caseinfolist.append(ArgNameList)
  143. return caseinfolist
  144. #获取输入
  145. def get_input(Data, SuiteID, CaseID, caseinfolist):
  146. sArge=''
  147. #参数组合
  148. for j in range(0, caseinfolist[1]):
  149. if Data.read_data(SuiteID, Data.casebegin+CaseID, Data.argbegin+j) != "None":
  150. sArge=sArge+caseinfolist[2][j]+'='+Data.read_data(SuiteID, Data.casebegin+CaseID, Data.argbegin+j)+'&'
  151. #去掉结尾的&字符
  152. if sArge[-1:]=='&':
  153. sArge = sArge[0:-1]
  154. sInput=caseinfolist[0]+sArge    #组合全部参数
  155. return sInput
  156. #结果判断
  157. def assert_result(sReal, sExpect):
  158. sReal=str(sReal)
  159. sExpect=str(sExpect)
  160. if sReal==sExpect:
  161. return 'OK'
  162. else:
  163. return 'NG'
  164. #将测试结果写入文件
  165. def write_result(Data, SuiteId, CaseId, resultcol, *result):
  166. if len(result)>1:
  167. ret='OK'
  168. for i in range(0, len(result)):
  169. if result[i]=='NG':
  170. ret='NG'
  171. break
  172. if ret=='NG':
  173. Data.write_data(SuiteId, Data.casebegin+CaseId, resultcol,ret, NG_COLOR)
  174. else:
  175. Data.write_data(SuiteId, Data.casebegin+CaseId, resultcol,ret, OK_COLOR)
  176. Data.allresult.append(ret)
  177. else:
  178. if result[0]=='NG':
  179. Data.write_data(SuiteId, Data.casebegin+CaseId, resultcol,result[0], NG_COLOR)
  180. elif result[0]=='OK':
  181. Data.write_data(SuiteId, Data.casebegin+CaseId, resultcol,result[0], OK_COLOR)
  182. else:  #NT
  183. Data.write_data(SuiteId, Data.casebegin+CaseId, resultcol,result[0], NT_COLOR)
  184. Data.allresult.append(result[0])
  185. #将当前结果立即打印
  186. print 'case'+str(CaseId+1)+':', Data.allresult[-1]
  187. #打印测试结果
  188. def statisticresult(excelobj):
  189. allresultlist=excelobj.allresult
  190. count=[0, 0, 0]
  191. for i in range(0, len(allresultlist)):
  192. #print 'case'+str(i+1)+':', allresultlist[i]
  193. count=countflag(allresultlist[i],count[0], count[1], count[2])
  194. print 'Statistic result as follow:'
  195. print 'OK:', count[0]
  196. print 'NG:', count[1]
  197. print 'NT:', count[2]
  198. #解析XmlString返回Dict
  199. def get_xmlstring_dict(xml_string):
  200. xml = XML2Dict()
  201. return xml.fromstring(xml_string)
  202. #解析XmlFile返回Dict
  203. def get_xmlfile_dict(xml_file):
  204. xml = XML2Dict()
  205. return xml.parse(xml_file)
  206. #去除历史数据expect[real]
  207. def delcomment(excelobj, suiteid, iRow, iCol, str):
  208. startpos = str.find('[')
  209. if startpos>0:
  210. str = str[0:startpos].strip()
  211. excelobj.write_data(suiteid, iRow, iCol, str, OK_COLOR)
  212. return str
  213. #检查每个item (非结构体)
  214. def check_item(excelobj, suiteid, caseid,real_dict, checklist, begincol):
  215. ret='OK'
  216. for checkid in range(0, len(checklist)):
  217. real=real_dict[checklist[checkid]]['value']
  218. expect=excelobj.read_data(suiteid, excelobj.casebegin+caseid, begincol+checkid)
  219. #如果检查不一致测将实际结果写入expect字段,格式:expect[real]
  220. #将return NG
  221. result=assert_result(real, expect)
  222. if result=='NG':
  223. writestr=expect+'['+real+']'
  224. excelobj.write_data(suiteid, excelobj.casebegin+caseid, begincol+checkid, writestr, NG_COLOR)
  225. ret='NG'
  226. return ret
  227. #检查结构体类型
  228. def check_struct_item(excelobj, suiteid, caseid,real_struct_dict, structlist, structbegin, structcount):
  229. ret='OK'
  230. if structcount>1:  #传入的是List
  231. for structid in range(0, structcount):
  232. structdict=real_struct_dict[structid]
  233. temp=check_item(excelobj, suiteid, caseid,structdict, structlist, structbegin+structid*len(structlist))
  234. if temp=='NG':
  235. ret='NG'
  236. else: #传入的是Dict
  237. temp=check_item(excelobj, suiteid, caseid,real_struct_dict, structlist, structbegin)
  238. if temp=='NG':
  239. ret='NG'
  240. return ret
  241. #获取异常函数及行号
  242. def print_error_info():
  243. """Return the frame object for the caller's stack frame."""
  244. try:
  245. raise Exception
  246. except:
  247. f = sys.exc_info()[2].tb_frame.f_back
  248. print (f.f_code.co_name, f.f_lineno)
  249. #测试结果计数器,类似Switch语句实现
  250. def countflag(flag,ok, ng, nt):
  251. calculation  = {'OK':lambda:[ok+1, ng, nt],
  252. 'NG':lambda:[ok, ng+1, nt],
  253. 'NT':lambda:[ok, ng, nt+1]}
  254. return calculation[flag]()

2、项目测试代码

  1. # -*- coding: utf-8 -*-
  2. #****************************************************************
  3. # xxx_server_case.py
  4. # Author     : Vince
  5. # Version    : 1.0
  6. # Date       : 2011-3-10
  7. # Description: 内容服务系统测试代码
  8. #****************************************************************
  9. from testframe import *
  10. from common_lib import *
  11. httpString='http://xxx.com/xxx_product/test/'
  12. expectXmldir=os.getcwd()+'/TestDir/expect/'
  13. realXmldir=os.getcwd()+'/TestDir/real/'
  14. def run(interface_name, suiteid):
  15. print '【'+interface_name+'】' + ' Test Begin,please waiting...'
  16. global expectXmldir, realXmldir
  17. #根据接口名分别创建预期结果目录和实际结果目录
  18. expectDir=expectXmldir+interface_name
  19. realDir=realXmldir+interface_name
  20. if os.path.exists(expectDir) == 0:
  21. os.makedirs(expectDir)
  22. if os.path.exists(realDir) == 0:
  23. os.makedirs(realDir)
  24. excelobj.del_testrecord(suiteid)  #清除历史测试数据
  25. casecount=excelobj.get_ncase(suiteid) #获取case个数
  26. caseinfolist=get_caseinfo(excelobj, suiteid) #获取Case基本信息
  27. #遍历执行case
  28. for caseid in range(0, casecount):
  29. #检查是否执行该Case
  30. if excelobj.read_data(suiteid,excelobj.casebegin+caseid, 2)=='N':
  31. write_result(excelobj, suiteid, caseid, excelobj.resultCol, 'NT')
  32. continue #当前Case结束,继续执行下一个Case
  33. #获取测试数据
  34. sInput=httpString+get_input(excelobj, suiteid, caseid, caseinfolist)
  35. XmlString=HTTPInvoke(com_ipport, sInput)     #执行调用
  36. #获取返回码并比较
  37. result_code=et.fromstring(XmlString).find("result_code").text
  38. ret1=check_result(excelobj, suiteid, caseid,result_code, excelobj.retCol)
  39. #保存预期结果文件
  40. expectPath=expectDir+'/'+str(caseid+1)+'.xml'
  41. #saveXmlfile(expectPath, XmlString)
  42. #保存实际结果文件
  43. realPath=realDir+'/'+str(caseid+1)+'.xml'
  44. saveXmlfile(realPath, XmlString)
  45. #比较预期结果和实际结果
  46. ret2= check_xmlfile(excelobj, suiteid, caseid,expectPath, realPath)
  47. #写测试结果
  48. write_result(excelobj, suiteid, caseid, excelobj.resultCol, ret1, ret2)
  49. print '【'+interface_name+'】' + ' Test End!'

3、测试入口

  1. # -*- coding: utf-8 -*-
  2. #****************************************************************
  3. # main.py
  4. # Author     : Vince
  5. # Version    : 1.0
  6. # Date       : 2011-3-16
  7. # Description: 测试组装,用例执行入口
  8. #****************************************************************
  9. from testframe import *
  10. from xxx_server_case import *
  11. import xxx_server_case
  12. #产品系统接口测试
  13. #设置测试环境
  14. xxx_server_case.excelobj=create_excel(os.getcwd()+'/TestDir/xxx_Testcase.xls')
  15. xxx_server_case.com_ipport=xxx.com'
  16. #Add testsuite begin
  17. run("xxx_book_list", 4)
  18. #Add other suite from here
  19. #Add testsuite end
  20. statisticresult(xxx_server_case.excelobj)
  21. xxx_server_case.excelobj.close()

http接口自动化测试框架实现的更多相关文章

  1. 接口测试入门(4)--接口自动化测试框架 / list和map用法 / 随机选取新闻 (随机数生成) / 接口相关id映射

    一.接口自动化测试框架 为了更好的组织测试方法,测试用例并且持续集成,我们选择了  java+testNG(测试用例组织)+gitlab(代码版本管理)+Jenkins(持续集成工具) 作为一整套的自 ...

  2. python版接口自动化测试框架源码完整版(requests + unittest)

    python版接口自动化测试框架:https://gitee.com/UncleYong/my_rf [框架目录结构介绍] bin: 可执行文件,程序入口 conf: 配置文件 core: 核心文件 ...

  3. 接口自动化 [授客]基于python+Testlink+Jenkins实现的接口自动化测试框架V3.0

    基于python+Testlink+Jenkins实现的接口自动化测试框架V3.0   by:授客 QQ:1033553122     博客:http://blog.sina.com.cn/ishou ...

  4. 接口自动化 基于python+Testlink+Jenkins实现的接口自动化测试框架[V2.0改进版]

    基于python+Testlink+Jenkins实现的接口自动化测试框架[V2.0改进版]   by:授客 QQ:1033553122 由于篇幅问题,,暂且采用网盘分享的形式: 下载地址: [授客] ...

  5. 基于python+Testlink+Jenkins实现的接口自动化测试框架V3.0

    基于python+Testlink+Jenkins实现的接口自动化测试框架V3.0 目录 1. 开发环境2. 主要功能逻辑介绍3. 框架功能简介 4. 数据库的创建 5. 框架模块详细介绍6. Tes ...

  6. 【转】robot framework + python实现http接口自动化测试框架

    前言 下周即将展开一个http接口测试的需求,刚刚完成的java类接口测试工作中,由于之前犯懒,没有提前搭建好自动化回归测试框架,以至于后期rd每修改一个bug,经常导致之前没有问题的case又产生了 ...

  7. 【python3+request】python3+requests接口自动化测试框架实例详解教程

    转自:https://my.oschina.net/u/3041656/blog/820023 [python3+request]python3+requests接口自动化测试框架实例详解教程 前段时 ...

  8. 接口自动化 基于python实现的http+json协议接口自动化测试框架源码(实用改进版)

    基于python实现的http+json协议接口自动化测试框架(实用改进版)   by:授客 QQ:1033553122 欢迎加入软件性能测试交流QQ群:7156436     目录 1.      ...

  9. Python 基于python实现的http接口自动化测试框架(含源码)

    基于python实现的http+json协议接口自动化测试框架(含源码) by:授客 QQ:1033553122      欢迎加入软件性能测试交流 QQ群:7156436  由于篇幅问题,采用百度网 ...

  10. robot framework + python实现http接口自动化测试框架

    https://www.jianshu.com/p/6d1e8cb90e7d 前言 下周即将展开一个http接口测试的需求,刚刚完成的java类接口测试工作中,由于之前犯懒,没有提前搭建好自动化回归测 ...

随机推荐

  1. Servlet 简单介绍

    来源于菜鸟教程http://www.runoob.com/servlet/servlet-intro.html Servlet 简介 Servlet 是什么? Servlet(Server Apple ...

  2. SharpGL学习笔记(二) 模型变换(几何变换)

    (二) 模型变换 模形变换就是指的在世界坐标系中(world space)做“移动”,“旋转", "缩放"三种操作. 首先要说明的,在Opengl中,是用4x4矩阵进行坐 ...

  3. 斐讯K2刷不死breed与第三方固件教程

    本文主要就是简单的斐讯 K2 刷机教程,方便大家了解一下 K2 怎样刷固件.斐讯 K2 是一款 1200M AC 双频无线路由器,支持 5G 和 2.4G WiFi 信号,虽然缺少 USB 且只有百兆 ...

  4. rsyslog local0-local7的用法

    很多时候我们需要将一个服务的日志文件导向一个指定的文件,这个时候可以设置log-facility 如在dhcpd.conf中配置 1 : update log-facility in the dhcp ...

  5. psr-4

    自动加载: <?php function autoload($className) { $className = ltrim($className, '\\'); $fileName = ''; ...

  6. python pytest测试框架介绍三

    之前介绍了pytest以xUnit形式来写用例,下面来介绍pytest特有的方式来写用例 1.pytest fixture实例1 代码如下 from __future__ import print_f ...

  7. thinkCMF----调用幻灯片

    还是在Common.php上写: /* * slide 获取幻灯片 * 具体使用: <?php $slide = slide();?> <foreach name="sli ...

  8. PAT天梯赛L2-003 月饼【贪心】

    L2-003. 月饼 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不 ...

  9. ASP.NET Web配置指南

    利用ASP.NET,可以指定影响服务器上所有的Web应用程序.仅影响单个的应用程序.影响个别页面.或影响Web应用程序中的个别文件夹的配置设置.可以对编译器选项.调试.用户身份验证.错误消息显示.连接 ...

  10. 一些常用的opencv函数

    分配图像空间: IplImage* cvCreateImage(CvSize size, int depth, int channels);       size:  cvSize(width,hei ...