http接口自动化测试框架实现

简介: http接口自动化测试框架实现作者:张元礼http://blog.csdn.net/vincetest 一、测试需求描述对服务后台一系列的http接口功能测试。输入:根据接口描述构造不同的参数输入值输出:XML文件eg:http://xxx.com/xxx_product/test/content_book_list.jsp?listid=1 二、实现方法1、选用Python脚本来驱动测试2、采用Excel表格管理测试数据,包括用例的管理、测试数据录入、测试结果显示等等,这个需要封装一个Excel的类即可。

http接口自动化测试框架实现

作者:张元礼

http://blog.csdn.net/vincetest 

一、测试需求描述

对服务后台一系列的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、测试框架代码

 

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

 

2、项目测试代码

 

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

 

3、测试入口

 

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

 

 

最后感谢我的同事Roger为此做了一些优化,后续优化的东东还很多,我们一直在努力!

欢迎转载此文,转载时请注明文章来源:张元礼的博客 http://blog.csdn.net/vincetest

相关文章
|
6天前
|
敏捷开发 Java 测试技术
探索软件测试中的自动化测试框架
在软件开发的生命周期中,软件测试扮演着至关重要的角色。随着技术的不断进步和软件项目的日益复杂化,传统的手动测试方法已经无法满足高效、准确的测试需求。自动化测试作为一种提高测试效率和质量的有效手段,越来越受到开发者和测试者的青睐。本文将深入探讨自动化测试框架的重要性、常见的自动化测试工具以及如何选择合适的自动化测试框架。
33 10
|
8天前
|
设计模式 前端开发 JavaScript
自动化测试框架设计原则与最佳实践####
本文深入探讨了构建高效、可维护的自动化测试框架的核心原则与策略,旨在为软件测试工程师提供一套系统性的方法指南。通过分析常见误区,结合行业案例,阐述了如何根据项目特性定制自动化策略,优化测试流程,提升测试覆盖率与执行效率。 ####
32 6
|
8天前
|
人工智能 前端开发 测试技术
探索软件测试中的自动化框架选择与优化策略####
本文深入剖析了当前主流的自动化测试框架,通过对比分析各自的优势、局限性及适用场景,为读者提供了一套系统性的选择与优化指南。文章首先概述了自动化测试的重要性及其在软件开发生命周期中的位置,接着逐一探讨了Selenium、Appium、Cypress等热门框架的特点,并通过实际案例展示了如何根据项目需求灵活选用与配置框架,以提升测试效率和质量。最后,文章还分享了若干最佳实践和未来趋势预测,旨在帮助测试工程师更好地应对复杂多变的测试环境。 ####
30 4
|
8天前
|
监控 jenkins 测试技术
自动化测试框架的构建与实践
【10月更文挑战第40天】在软件开发周期中,测试环节扮演着至关重要的角色。本文将引导你了解如何构建一个高效的自动化测试框架,并深入探讨其设计原则、实现方法及维护策略。通过实际代码示例和清晰的步骤说明,我们将一起探索如何确保软件质量,同时提升开发效率。
22 1
|
12天前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
|
14天前
|
机器学习/深度学习 前端开发 测试技术
探索软件测试中的自动化测试框架选择与优化策略####
本文深入探讨了在当前软件开发生命周期中,自动化测试框架的选择对于提升测试效率、保障产品质量的重要性。通过分析市场上主流的自动化测试工具,如Selenium、Appium、Jest等,结合具体项目需求,提出了一套系统化的选型与优化策略。文章首先概述了自动化测试的基本原理及其在现代软件开发中的角色变迁,随后详细对比了各主流框架的功能特点、适用场景及优缺点,最后基于实际案例,阐述了如何根据项目特性量身定制自动化测试解决方案,并给出了持续集成/持续部署(CI/CD)环境下的最佳实践建议。 --- ####
|
15天前
|
Java 测试技术 持续交付
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
本文重点讲解如何搭建App自动化测试框架的思路,而非完整源码。主要内容包括实现目的、框架设计、环境依赖和框架的主要组成部分。适用于初学者,旨在帮助其快速掌握App自动化测试的基本技能。文中详细介绍了从需求分析到技术栈选择,再到具体模块的封装与实现,包括登录、截图、日志、测试报告和邮件服务等。同时提供了运行效果的展示,便于理解和实践。
58 4
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
|
3天前
|
JavaScript 安全 编译器
TypeScript 与 Jest 测试框架的结合使用,从 TypeScript 的测试需求出发,介绍了 Jest 的特点及其与 TypeScript 结合的优势,详细讲解了基本测试步骤、常见测试场景及异步操作测试方法
本文深入探讨了 TypeScript 与 Jest 测试框架的结合使用,从 TypeScript 的测试需求出发,介绍了 Jest 的特点及其与 TypeScript 结合的优势,详细讲解了基本测试步骤、常见测试场景及异步操作测试方法,并通过实际案例展示了其在项目中的应用效果,旨在提升代码质量和开发效率。
19 6
|
5天前
|
jenkins 测试技术 持续交付
自动化测试框架的构建与优化:提升软件交付效率的关键####
本文深入探讨了自动化测试框架的核心价值,通过对比传统手工测试方法的局限性,揭示了自动化测试在现代软件开发生命周期中的重要性。不同于常规摘要仅概述内容,本部分强调了自动化测试如何显著提高测试覆盖率、缩短测试周期、降低人力成本,并促进持续集成/持续部署(CI/CD)流程的实施,最终实现软件质量和开发效率的双重飞跃。通过具体案例分析,展示了从零开始构建自动化测试框架的策略与最佳实践,包括选择合适的工具、设计高效的测试用例结构、以及如何进行性能调优等关键步骤。此外,还讨论了在实施过程中可能遇到的挑战及应对策略,为读者提供了一套可操作的优化指南。 ####
|
11天前
|
安全 前端开发 测试技术
如何选择合适的自动化安全测试工具
选择合适的自动化安全测试工具需考虑多个因素,包括项目需求、测试目标、系统类型和技术栈,工具的功能特性、市场评价、成本和许可,以及集成性、误报率、社区支持、易用性和安全性。综合评估这些因素,可确保所选工具满足项目需求和团队能力。

热门文章

最新文章