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

news2025/1/20 16:24:35

上午在园子里乱逛,看了不少小伙伴们分享的接口测试方面的知识,仔细想想,我做接口测试也有几个年头了,大家所叙述到的一些经验或多或少,我也曾遇到过,突然意识到知识的点滴积累是多么的重要,我记得我最早接触接口测试的时候,就是只在浏览器里人工测试单个接口的返回结果,后来用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.password
          tmp=res.fetch_res(url)    
          result = json.loads(tmp)
          return result
      def 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.password
          result=res.fetch_status(url)
          return result    
      def token(self):
          result=''
          if self.ret==1:
              result= self.jsonData["data"]["token"]
          return result
      def uClen(self):
          result=''
          if self.ret==1:
              result=len(self.jsonData["data"]["userCapital"])
          return result
      def uCuserId(self):
          result=''
          if self.ret==1:  
              result=self.jsonData["data"]["userCapital"]["userId"]
          return result
      def 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 result
            else:
                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 = void
    
    def do(self):#访问接口并保存结果
        cookie=cookielib.CookieJar()
        opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))
        try:
            req=opener.open(self.__firstUrl)
            self.status=req.code
        except urllib2.HTTPError, e:
            self.status= e.code
        if self.status==200:
            for cj in cookie:
                if cj.name=='JSESSIONID':
                    session= cj.value
            req=urllib2.Request(self.__url)
            data=urllib.urlencode(self.__parameter)
            try:
                tmp = opener.open(req,data)
                self.status=tmp.code
            except urllib2.HTTPError, e:
                self.status=e.code
            if 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.actualList
        return result
    _typeDict["actual"] = "String"
    def actual(self):#调用module函数比较测试结果
        result=module.outPut(self.actualList)  
        return result 

测试结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1064179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SRTP交叉编译与移植

1 SRTP源码下载 源码下载在github采用的库为libsrtp2.5.0: weget https://github.com/cisco/libsrtp/archive/refs/tags/v2.5.0.tar.gz2 SRTP交叉编译 新增交叉编译脚本&#xff0c;这里需要支持openssl。 ./configure --hostarm-linux-androideabi --prefix$(pwd)/object …

基于python的GUI设计

GUI设计是编程应用的一个重要载体&#xff0c;是软件开发实现的重要步骤&#xff0c;需要重要掌握&#xff0c;不管是C、JAVA、python、matlab等编程语言&#xff0c;都需要GUI界面设计来实验软件开发的前期工作&#xff0c;同时也方便按钮操作。 在设计GUI的过程中&#xff0…

ZRTP协议与原理

1 ZRTP简介 ZRTP&#xff0c;全名Z Real-time Transport Protocol&#xff0c;是一种网络协议&#xff0c;旨在为实时通信提供安全性。与其它安全协议&#xff08;如TLS和IPsec&#xff09;不同&#xff0c;ZRTP专门为实时通信设计&#xff0c;包括音频和视频通话。它是由Phil…

竞赛 深度学习 opencv python 公式识别(图像识别 机器视觉)

文章目录 0 前言1 课题说明2 效果展示3 具体实现4 关键代码实现5 算法综合效果6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习的数学公式识别算法实现 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学…

支付环境安全漏洞介绍

1、平台支付逻辑全流程分析 2、平台支付漏洞如何利用&#xff1f;买东西还送钱&#xff1f; 3、BURP抓包分析修改支付金额&#xff0c;伪造交易状态&#xff1f; 4、修改购物车参数实现底价购买商品 5、SRC、CTF、HW项目月入10W副业之路 6、如何构建最适合自己的网安学习路线 1…

netcore Polly.Core

一、安装包 <PackageReference Include"Polly.Core" Version"8.0.0" /> 二、编写重试 ResiliencePipeline pipeline new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions{MaxRetryAttempts 2,Delay TimeSpan.FromSeconds(3),O…

竞赛 机器视觉目标检测 - opencv 深度学习

文章目录 0 前言2 目标检测概念3 目标分类、定位、检测示例4 传统目标检测5 两类目标检测算法5.1 相关研究5.1.1 选择性搜索5.1.2 OverFeat 5.2 基于区域提名的方法5.2.1 R-CNN5.2.2 SPP-net5.2.3 Fast R-CNN 5.3 端到端的方法YOLOSSD 6 人体检测结果7 最后 0 前言 &#x1f5…

Flink的处理函数——processFunction

目录 一、处理函数概述 二、Process函数分类——8个 &#xff08;1&#xff09;ProcessFunction &#xff08;2&#xff09;KeyedProcessFunction &#xff08;3&#xff09;ProcessWindowFunction &#xff08;4&#xff09;ProcessAllWindowFunction &#xff…

CSDN Markdown

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

数据中台实战(05)-如何统一管理纷繁杂乱的数据指标?

各种类型的元数据有什么用&#xff1f;跟数据中台啥关系&#xff1f; 元数据在指标管理、模型设计、数据质量和成本治理四个领域都发挥作用&#xff0c;这些领域构成数据中台OneData 数据体系。今天逐一了解元数据在上述领域的应用 1 指标管理 指标&#xff0c;一种特定类型…

【Java项目推荐之黑马头条】你的发布文章业务是怎么实现的?

前言 在学习Java的路上还是遇到了很多不错的好项目的&#xff0c;今天分享给大家&#xff0c;希望能对大家面试有所帮助&#xff01; 后续会继续推荐其他好的项目&#xff0c;这次推荐的是B站开源的视频黑马头条项目&#xff0c;来吧学会它一起去虐面试官&#xff01;&#x…

MySQL:增量备份和恢复(5)

介绍 增量备份的特点 MySQL数据库二进制日志对备份的意义 增量备份的优点是没有重复数据&#xff0c;备份量不大&#xff0c;时间短。缺点也很明显&#xff0c;需要上次完全备份及完全备份之后所有的增量备份才能恢复&#xff0c;反推恢复&#xff0c;操作较为繁琐。 Mysql没有…

buildroot添加package包

本文通过一个简单的例子介绍如何在 RK3568的buildroot/package 目录下添加一个自己的 package&#xff08;软件包&#xff09; 一、开发源码工程 首先进入/app 目录下&#xff0c;在该目录下创建一个名为“mypackage”的文件夹&#xff0c;如下所示&#xff1a;   在 mypac…

LVGL_基础控件进度条bar

LVGL_基础控件进度条bar 1、创建进度条控件 // 创建一个 bar 组件(对象)&#xff0c;他的父对象是活动屏幕对象lv_obj_t *bar lv_bar_create(lv_scr_act()); LV_LOG_USER("lv_bar_get_value(bar) %d", lv_bar_get_value(bar));/* 设置位置 */ lv_obj_center(bar);…

Linux 安装字体

1.进入/usr/share/fonts路径&#xff0c;为了方便区分新安装的字体&#xff0c;最好单独创建文件夹 2.把需要安装的字体解压到自己创建的文件夹里面&#xff0c;这里要安装Hack 字体 3.输入以下三条命令如下图所示 ####三条命令要在字体路径下执行 sudo mkfontscale sudo mkfo…

【产品设计】如何开展你的B端产品需求调研

对于B端产品来说&#xff0c;需求调研是经常做而且很重要的一件事&#xff0c;只有对需求足够了解&#xff0c;才能设计出大众所喜欢的、市场所需要的好的产品。那么&#xff0c;应该如何开始你的需求调研呢&#xff1f;需求调研的执行过程又是怎样的&#xff1f;如何对结果进行…

快排(三种单趟排序法,递归非递归算法)

快排发明者:霍尔 (Sir Charles Antony Richard Hoare) 是一位英国计算机科学家。 计算机领域的爵士——托尼霍尔(Tony Hoare)(1934年1月11日出生),英文全称Sir Charles Antony Richard Hoare,常被称为Tony Hoare或者C. A. R. Hoare,1959年博士毕业于

Java方法:重复使用的操作可以写成方法哦

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、方法的概念1、什么是方法&#xff1f;2、方法的定义3、方法调用的过程 二、方法重载1、重载的概念2、方法签名 在日常生活中…

elementui修改message消息提示颜色

/* el弹出框样式 */ .el-message {top: 80px !important;border: 0; }.el-message * {color: var(--white) !important;font-weight: 600; }.el-message--success {background: var(--themeBackground); }.el-message--warning {background: var(--gradientBG); }.el-message--…

按键精灵调用大漠插件源码例子

源码名称&#xff1a;按键精灵调用大漠插件例子源码完整备注 源码名称&#xff1a;按键精灵调用大漠插件例子源码完整备注 蓝奏下载&#xff1a;https://wwi.lanzoup.com/iuffr0riiowf 飞书网盘&#xff1a;Docs