利用fitnesse实现api接口自动化测试

2023-10-06 21:26

本文主要是介绍利用fitnesse实现api接口自动化测试,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上午在园子里乱逛,看了不少小伙伴们分享的接口测试方面的知识,仔细想想,我做接口测试也有几个年头了,大家所叙述到的一些经验或多或少,我也曾遇到过,突然意识到知识的点滴积累是多么的重要,我记得我最早接触接口测试的时候,就是只在浏览器里人工测试单个接口的返回结果,后来用python的unittest自己写测试框架,和现在大多数小伙伴们的方法差不多,测试用例也是存放在excle表中,这对于单人测试来说都还ok,但是如果是多人协同测试时,问题就出来了,因为按目录存放在不同的excle表中的测试用例,维护起来比较麻烦,而且不便于多人查询或共同维护测试用例。所以之前的公司老大给我们推荐了一个工具——fitnesse,它是用wiki方式在界面上管理测试用例,驱动后台脚本进行测试,因为测试用例界面是个wiki地址,可以很方便的和大家一起协同工作,而且用例查询和维护起来都方便的多。

      我在之前的公司用了将近一年这个工具,但是因为刚休完产假的自己工作状态非常不好,其实并没有在这方面很尽心,只到来了新公司后,才又一次重新学习使用起这个工具来,还是api接口测试,年前我从不同的角度分别写了几个不同的demo,虽然现在大多数用fitnesse的人都是用的slim引擎,但是因为java helloworld水平的我一直用的python,找不到合适的支持slim的python插件,所以还是用的fitnesse的fit引擎,用PyFIT支持起来。

     对于api接口功能测试,我个人认为需要关注的有这几个方面:接口状态,响应时间,字段格式,返回数据,想起来之前面试阿里时,提到接口测试,他问了我很多http协议类的,具体问题记不清了,大概是几次握手交互那类的,额,不知道是不是关注点不同的缘故,他问得几个关于接口测试的问题我都没用过,其实到现在我还是有些疑惑的,不知道是他理解的接口测试和我理解的有偏差,不过也许是我涉猎的领域太窄,对于接口应该怎么充分测试我是比较怀疑了,也经常会在网上翻阅关于接口测试的文档,但是感觉收效甚微,嗯,对于未知领域的探索仍在继续,对于已知领域的小果子,拿出来和小伙伴一起分享下吧

     所测接口:api接口,返回结果json格式

     所用工具:fitnesse,fit引擎,python

第一种方式:

   测试思想:在页面上初始化测试数据,将接口的返回结果按每个字段逐一填写期望结果,和接口的实际结果比较

   测试数据准备:在界面上利用sql语句初始化测试数据,然后在测试用例页面included 该页面

  测试用例:将json各个字段拆开填写到测试用例表格中,用ColumnFixture,测试用例格式如下

baseurl:接口基本不变的部分,这一部分可以在表格外参数化然后传值到表格里,account和password是接口的两个输入参数,带?标识的是要验证的结果,将json返回结果的每个字段都拆开填写在表格中。


后台脚本:


class LoginTest(ColumnFixture):_typeDict = {"description":"String","BaseUrl":"String","account":"String","password":"String","status":"Int","retMsg":"String","token":"String","uClen":"Int","uCuserId":"Int","uCamount":"String",}def __init__(self):   ColumnFixture.__init__(self)self.account=''self.password=''self.BaseUrl=''self.jsonData='' self.ret=''      def getRes(self):                url=self.BaseUrl+"account="+self.account+"&password="+self.passwordtmp=res.fetch_res(url)    result = json.loads(tmp)return resultdef retMsg(self):self.jsonData=self.getRes()self.ret=self.jsonData["ret"]result=str(self.jsonData["ret"])+self.jsonData["msg"]return result def status(self):url=self.BaseUrl+"account="+self.account+"&password="+self.passwordresult=res.fetch_status(url)return result    def token(self):result=''if self.ret==1:result= self.jsonData["data"]["token"]return resultdef uClen(self):result=''if self.ret==1:result=len(self.jsonData["data"]["userCapital"])return resultdef uCuserId(self):result=''if self.ret==1:  result=self.jsonData["data"]["userCapital"]["userId"]return resultdef uCamount(self):result=''if self.ret==1:result=str(self.jsonData["data"]["userCapital"]["amount"])return result

优点:测试脚本结构简单,测试用例格式清晰,缺点:如果接口返回层级或字段较多时,不便于测试用例维护,需要初始化测试数据并清除增加的数据,部分动态字段(比如creattime)无法准确校验

第二种方式:

测试思想:在已有数据库基础上,无需每次添加测试数据,在测试脚本中根据需求用sql语句检索出对应字段的数据,作为期望结果,和接口的实际结果比较

测试数据:已有数据库基础上

测试用例:

 测试脚本部分示例:

def retMsg(self):if self.status==200: self.jsonData=self.getRes()isUserSql="SELECT * FROM hcm_user WHERE NAME LIKE \'"+self.account+"\' AND PASSWORD LIKE \'"+self.password+ "\'AND TYPE=0"self.isUser=db.queryDb(isUserSql)              self.ret=self.jsonData["ret"]result=str(self.jsonData["ret"])+self.jsonData["msg"]return resultelse:return ''def securityStatusCheck(self):symbol="="list=['userId','userName','emailStatus','mobileStatus','realNameAuthStatus','autoTransfer','trusteeshipAccountStatus']dataJson=[]dataCase=[]if self.isUser:sql="SELECT a.id,a.`name`,IF(a.email!='',1,0),IF(a.`mobile`,1,0),b.`yeepay_account_status`,b.auto_transfer,b.`yeepay_account_status` FROM hcm_user a,hcm_user_auth b WHERE NAME LIKE '"+self.account+"' AND a.id=b.user_id"               data=db.queryDb(sql)if data:for i in range (0,len(list)):dataCase.append(list[i]+symbol+str(data[0][i]))if self.ret==1:tmp=self.jsonData["data"]["securityStatus"]for i in range (0,len(list)):dataJson.append(list[i]+symbol+str(tmp[list[i]]))result=Check(dataJson, dataCase)return result

测试结果:

突然发现给自己写优缺点好二啊,反正就是上面两种都没有满足老大们的要求,他们希望我能写一个通用的框架,让没有任何编码能力的人也能进行接口测试,即只需要前台编写测试用例,不用管后台脚本就能进行测试,于是乎有了下面第三种方式

第三种方式:

测试思想:满足老大们的要求,不用编写任何脚本即可进行接口测试

测试数据:固定初始化好的数据库

测试用例:

其中,firsturl是被依赖的登录接口,url是所测接口,blackLIst是希望过滤de返回字段的黑名单(比如ordeId,每次都是变化的,无法准确校验,添加到黑名单中即可不对其校验),data是期望结果,因为所测接口需要先登录然后保持session,才能返回正常结果,所以此处采用的是fit的Actionfixture测试脚本示例:


from fit.Fixture import Fixture 
import urllib2,cookielib,urllib
import module,json
import sys
reload(sys)
sys.setdefaultencoding('UTF-8')class ActionTest(Fixture):_typeDict = {}def __init__(self):#初始化参数Fixture.__init__(self)self.__firstUrl  = ''   #< Private attributes (Python convention).self.__url = ''self.__parameter = ''self.__blackList=''self.__data=''self.res=''self.status=''self.expectedList=''self.actualList=''self.test=''_typeDict["firstUrl"] = "String"def firstUrl(self, s):self.__firstUrl = s_typeDict["url"] = "String"def url(self, s):self.__url = s_typeDict["parameter"] = "Dict"def parameter(self, s):self.__parameter = s_typeDict["blackList"] = "List"def blackList(self, s):self.__blackList = s_typeDict["data"] = "String"def data(self, s):self.__data = s_typeDict["do"] = "Default"      #< AUTO-DETECT: None = voiddef do(self):#访问接口并保存结果cookie=cookielib.CookieJar()opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))try:req=opener.open(self.__firstUrl)self.status=req.codeexcept urllib2.HTTPError, e:self.status= e.codeif self.status==200:for cj in cookie:if cj.name=='JSESSIONID':session= cj.valuereq=urllib2.Request(self.__url)data=urllib.urlencode(self.__parameter)try:tmp = opener.open(req,data)self.status=tmp.codeexcept urllib2.HTTPError, e:self.status=e.codeif self.status==200:self.res= tmp.read()else:self.res='{"status":"no 200"}'else:self.res='{"loginStatus":"no 200"}'_typeDict["status"] = "Int"def status(self):return self.status  _typeDict["expect"] = "String"def expect(self):#调用module函数比较测试结果self.expectedList=[]self.actualList=[]module.resultList(self.__blackList,self.__data, self.res, self.expectedList, self.actualList)#比较后将结果存放到输出数组中 result=module.outPut(self.expectedList)#tmp=unicode(self.__data, 'utf-8')#return str(self.actualListreturn result_typeDict["actual"] = "String"def actual(self):#调用module函数比较测试结果result=module.outPut(self.actualList)  return result 

测试结果:

这篇关于利用fitnesse实现api接口自动化测试的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/154059

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja