所测接口: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
测试结果:
突然发现给自己写优缺点好二啊,反正就是上面两种都没有满足老大们的要求,他们希望我能写一个通用的框架,让没有任何编码能力的人也能进行接口测试,即只需要前台编写测试用例,不用管后台脚本就能进行测试,于是乎有了下面第三种方式
测试思想:满足老大们的要求,不用编写任何脚本即可进行接口测试
测试数据:固定初始化好的数据库
测试用例:
脚本:
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
测试结果: