会网站制作的职业是,wordpress 七牛云插件,支持付费下载系统的网站模板或建站软件,生活中好的设计产品上午在园子里乱逛#xff0c;看了不少小伙伴们分享的接口测试方面的知识#xff0c;仔细想想#xff0c;我做接口测试也有几个年头了#xff0c;大家所叙述到的一些经验或多或少#xff0c;我也曾遇到过#xff0c;突然意识到知识的点滴积累是多么的重要#xff0c;我记…上午在园子里乱逛看了不少小伙伴们分享的接口测试方面的知识仔细想想我做接口测试也有几个年头了大家所叙述到的一些经验或多或少我也曾遇到过突然意识到知识的点滴积累是多么的重要我记得我最早接触接口测试的时候就是只在浏览器里人工测试单个接口的返回结果后来用python的unittest自己写测试框架和现在大多数小伙伴们的方法差不多测试用例也是存放在excle表中这对于单人测试来说都还ok但是如果是多人协同测试时问题就出来了因为按目录存放在不同的excle表中的测试用例维护起来比较麻烦而且不便于多人查询或共同维护测试用例。所以之前的公司老大给我们推荐了一个工具——fitnesse它是用wiki方式在界面上管理测试用例驱动后台脚本进行测试因为测试用例界面是个wiki地址可以很方便的和大家一起协同工作而且用例查询和维护起来都方便的多。 我在之前的公司用了将近一年这个工具但是因为刚休完产假的自己工作状态非常不好其实并没有在这方面很尽心只到来了新公司后才又一次重新学习使用起这个工具来还是api接口测试年前我从不同的角度分别写了几个不同的demo虽然现在大多数用fitnesse的人都是用的slim引擎但是因为java helloworld水平的我一直用的python找不到合适的支持slim的python插件所以还是用的fitnesse的fit引擎用PyFIT支持起来。 对于api接口功能测试我个人认为需要关注的有这几个方面接口状态响应时间字段格式返回数据想起来之前面试阿里时提到接口测试他问了我很多http协议类的具体问题记不清了大概是几次握手交互那类的额不知道是不是关注点不同的缘故他问得几个关于接口测试的问题我都没用过其实到现在我还是有些疑惑的不知道是他理解的接口测试和我理解的有偏差不过也许是我涉猎的领域太窄对于接口应该怎么充分测试我是比较怀疑了也经常会在网上翻阅关于接口测试的文档但是感觉收效甚微嗯对于未知领域的探索仍在继续对于已知领域的小果子拿出来和小伙伴一起分享下吧 所测接口api接口返回结果json格式 所用工具fitnessefit引擎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.accountself.passwordself.BaseUrlself.jsonData self.ret def getRes(self): urlself.BaseUrlaccountself.accountpasswordself.passwordtmpres.fetch_res(url) result json.loads(tmp)return resultdef retMsg(self):self.jsonDataself.getRes()self.retself.jsonData[ret]resultstr(self.jsonData[ret])self.jsonData[msg]return result def status(self):urlself.BaseUrlaccountself.accountpasswordself.passwordresultres.fetch_status(url)return result def token(self):resultif self.ret1:result self.jsonData[data][token]return resultdef uClen(self):resultif self.ret1:resultlen(self.jsonData[data][userCapital])return resultdef uCuserId(self):resultif self.ret1: resultself.jsonData[data][userCapital][userId]return resultdef uCamount(self):resultif self.ret1:resultstr(self.jsonData[data][userCapital][amount])return result 优点测试脚本结构简单测试用例格式清晰缺点如果接口返回层级或字段较多时不便于测试用例维护需要初始化测试数据并清除增加的数据部分动态字段比如creattime无法准确校验
第二种方式
测试思想在已有数据库基础上无需每次添加测试数据在测试脚本中根据需求用sql语句检索出对应字段的数据作为期望结果和接口的实际结果比较
测试数据已有数据库基础上
测试用例 测试脚本部分示例
def retMsg(self):if self.status200: self.jsonDataself.getRes()isUserSqlSELECT * FROM hcm_user WHERE NAME LIKE \self.account\ AND PASSWORD LIKE \self.password \AND TYPE0self.isUserdb.queryDb(isUserSql) self.retself.jsonData[ret]resultstr(self.jsonData[ret])self.jsonData[msg]return resultelse:return def securityStatusCheck(self):symbollist[userId,userName,emailStatus,mobileStatus,realNameAuthStatus,autoTransfer,trusteeshipAccountStatus]dataJson[]dataCase[]if self.isUser:sqlSELECT 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.idb.user_id datadb.queryDb(sql)if data:for i in range (0,len(list)):dataCase.append(list[i]symbolstr(data[0][i]))if self.ret1:tmpself.jsonData[data][securityStatus]for i in range (0,len(list)):dataJson.append(list[i]symbolstr(tmp[list[i]]))resultCheck(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.__blackListself.__dataself.resself.statusself.expectedListself.actualListself.test_typeDict[firstUrl] Stringdef firstUrl(self, s):self.__firstUrl s_typeDict[url] Stringdef url(self, s):self.__url s_typeDict[parameter] Dictdef parameter(self, s):self.__parameter s_typeDict[blackList] Listdef blackList(self, s):self.__blackList s_typeDict[data] Stringdef data(self, s):self.__data s_typeDict[do] Default # AUTO-DETECT: None voiddef do(self):#访问接口并保存结果cookiecookielib.CookieJar()openerurllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))try:reqopener.open(self.__firstUrl)self.statusreq.codeexcept urllib2.HTTPError, e:self.status e.codeif self.status200:for cj in cookie:if cj.nameJSESSIONID:session cj.valuerequrllib2.Request(self.__url)dataurllib.urlencode(self.__parameter)try:tmp opener.open(req,data)self.statustmp.codeexcept urllib2.HTTPError, e:self.statuse.codeif self.status200:self.res tmp.read()else:self.res{status:no 200}else:self.res{loginStatus:no 200}_typeDict[status] Intdef status(self):return self.status _typeDict[expect] Stringdef expect(self):#调用module函数比较测试结果self.expectedList[]self.actualList[]module.resultList(self.__blackList,self.__data, self.res, self.expectedList, self.actualList)#比较后将结果存放到输出数组中 resultmodule.outPut(self.expectedList)#tmpunicode(self.__data, utf-8)#return str(self.actualListreturn result_typeDict[actual] Stringdef actual(self):#调用module函数比较测试结果resultmodule.outPut(self.actualList) return result 测试结果