通用技术 [分享] 自动化测试与持续集成方案--接口测试

snake · May 07, 2015 · Last by 王梦茹 replied at February 20, 2017 · 11045 hits
本帖已被设为精华帖!

有人在上一个帖子中问,为什么要把接口测试排在最前面。 原因很简单,接口是先行的,接口没做好,后面的编码工作受限,拿不到数据。

  1. 传统接口测试
  2. 接口自动化测试
  3. 接口自动化的持续集成
  4. 探讨

传统接口测试


不知道别人家的接口测试是怎么做的。这边是用postman这个google插件。测试人员按照接口开发人员的wiki,设计测试用例,然后post/get一下。查看返回json的状态或者字段。

弱点是不便于管理case和不方便统计结果,执行要一个一个手工去点,效率低下。

接口测试自动化


我用python写了个脚本,将case写在excel里,然后读取excel来实现这个过程,并自动判断和统计结果,生成报告。
case这么设计的。

脚本这么写的:

#encoding:utf-8

import ConfigParser
import os
import xlrd
import re
import httplib
import urllib
from urlparse import urlparse
import json
import time
import unittest
import pdf

currentdir=os.path.split(os.path.realpath(__file__))[0]
class test_class():
def getexcel(self):
casefile=currentdir + '/case.xls'
if ((os.path.exists(casefile))==False):
print "当前路径下没有case.xls,请检查!"
data=xlrd.open_workbook(casefile)
table = data.sheet_by_name('login')
nrows = table.nrows #行数
ncols = table.ncols #列数
#colnames = table.row_values(1) #某一行数据
for rownum in range(1,nrows):
for col in range (3, ncols):
value=table.cell(rownum,col).value
if (col==3):
method=value
if (col==4):
url=value
return table,nrows,ncols

def getexceldetail(self,table,row,ncols):
#rownum = table.row_values(row) #某一行数据

for col in range (0, ncols):
value=table.cell(row,col).value
if (col==0):
caseid=value
print caseid
if (col==3):
method=value
print method
if (col==4):
url=value
return method,url,caseid

def httpget(self,url):
httpClient = None
conn = urlparse(url)
url=url.encode('utf-8')
try:
httpClient = httplib.HTTPConnection(conn.netloc, timeout=10)
httpClient.request('GET', url)

# responseHTTPResponse对象
response = httpClient.getresponse()
print response
d0=response.read()
d0=d0.decode('unicode_escape')
except Exception, e:
print e
finally:
if httpClient:
httpClient.close()
return response.status,d0

def httppost(self,url):
httpClient = None
conn = urlparse(url)
url=url.encode('utf-8')
try:
header = {"Content-type": "application/x-www-form-urlencoded",
"Accept": "text/plain"}

httpClient = httplib.HTTPConnection(conn.netloc, timeout=30)
httpClient.request("POST", url)
response1 = httpClient.getresponse()
d1=response1.read()
d1=d1.decode('unicode_escape')
except Exception, e:
print e
finally:
if httpClient:
httpClient.close()
return response1.status,d1

代码太多了点,没写下。其实就是一个读excel,一个post,一个get的过程。
后面还有一个对json的解析过程。开始以为是一个字典就搞定了,后面发现有些{}里面嵌套了好几层。
最后用了个递归搞定。

#! /usr/bin/env python
#coding=utf-8
import urllib2
import json


class readjson():
def read(self,obj,key):
collect = list()
for k in obj:
v = obj[k]

if isinstance(v,str) or isinstance(v,unicode):
if key== ' ':
collect.append({k:v})
else:
collect.append({str(key)+"."+k:v})
elif isinstance(v,int):
if key== ' ':
collect.append({k:v})
else:
collect.append({str(key)+"."+k:v})
elif isinstance(v,bool):
if key== ' ':
collect.append({k:v})
else:
collect.append({str(key)+"."+k:v})
elif isinstance(v,dict):
collect.extend(read(v,k))
elif isinstance(v,list):
collect.extend(readList(v,key))
return collect

def readList(self,obj,key):
collect = list()
for index,item in enumerate(obj):
for k in item:
v = item[k]
if isinstance(v,str) or isinstance(v,unicode):
collect.append({key+"["+str(index)+"]"+"."+k:v})
elif isinstance(v,int):
collect.append({key+"["+str(index)+"]"+"."+k:v})
elif isinstance(v,bool):
collect.append({key+"["+str(index)+"]"+"."+k:v})
elif isinstance(v,dict):
collect.extend(read(v,key+"["+str(index)+"]"))
elif isinstance(v,list):
collect.extend(readList(v,key+"["+str(index)+"]"))
return collect


#ojt=test_data1

#print read(ojt,' ')

最后是结果:

是用python写图表,生成pdf.

from reportlab.graphics.shapes import Drawing  
from reportlab.graphics.charts.barcharts import VerticalBarChart
from urllib import urlopen
from reportlab.graphics.shapes import *
from reportlab.graphics.charts.lineplots import LinePlot
from reportlab.graphics.charts.textlabels import Label
from reportlab.graphics import renderPDF
class pdfreport():
def createpdf(self,datas):
drawing = Drawing(400, 200)
#data = [(13, 5, 20),(14, 6, 21)]
data=datas
bc = VerticalBarChart()
bc.x = 50
bc.y = 50
bc.height = 125
bc.width = 300
bc.data = data
bc.strokeColor = colors.black
bc.valueAxis.valueMin = 0
bc.valueAxis.valueMax = 50
bc.valueAxis.valueStep = 10
bc.categoryAxis.labels.boxAnchor ='ne'
bc.categoryAxis.labels.dx = 8
bc.categoryAxis.labels.dy = -2
bc.categoryAxis.labels.angle = 30
bc.categoryAxis.categoryNames = ['Jan-99','Feb-99','Mar-99']
#bc.categoryAxis.categoryNames =ytype
drawing.add(bc)

drawing.add(String(250,150,"ss", fontSize=14,fillColor=colors.red))
#drawing.add(String(250,150,des, fontSize=14,fillColor=colors.red))
renderPDF.drawToFile(drawing,'report1.pdf','API')
#renderPDF.drawToFile(drawing,'APIReport.pdf','API')

datas=[(0,20),(0,25)]
f=pdfreport()
f.createpdf(datas)

接口自动化的持续集成


配置到jenkins上也很简单,这里就不过多描述。现在问题是,生成的报告是pdf。Jenkins里面不太好展现出来。弄成zip附件查看不方便。最后我写个脚本将其传到共享里面,或者写脚本用邮件发出来。后面写打包的时候会讲到的。

探讨


这些脚本,还有很多可以完善的地方。我也没有花太多的精力去完善,我的宗旨是花少的时间,搞出简单又好用的东西。
上次看到思寒的一篇文章,就是自动生成接口的测试用例,这样效率大大提高了。
思寒:接口测试中数值 diff
遗憾的是,我没有完全搞明白他具体怎么做的,还要向思寒学习。

PS: 最近想挪窝,base上海,求收留。可以联系恒温和在群里找糖果

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 35 条回复 时间 点赞
snake #1 · May 07, 2015 作者

今天晚上要加个通宵的班,后面会停几天,我会坚持把后面的写完。

snake #2 · May 07, 2015 作者

同时继续寻找东家,没太多时间出去面试,就在这里毛遂自荐了。

恩。很好的方式。
接口多的话,都可以套个框架巡检起来了,逻辑也可以做深一点。

可以试试requests这个库,比urllib好用太多;JSON response可以直接用JSON库转化成字典:)

楼上说的对~

可惜base上海, 不然我们就要了.

我们是直接用jmeter来管理所有的接口,通过命令启动jmeter,写了个python脚本把jmeter生成的结果文件转化成需要的报告,在部署到jenkins上来实现持续集成,感觉这样比较简单,需要coding的部分就是生成报告这块啦~

接口传的参数也写在excel内写死的吗 我之前也是用Python的request json处理简便一点 楼主这个生成图表的不错 感觉你代码写得比我高端多了 nice·· :plus1:

snake #9 · May 11, 2015 作者

@jennyhui 这个就看你意愿了,可以写死,也可以写配置文件。

有想法,可以实际中使用有限制。
不如7楼说的直接用jmeter,而且Jenkins 中有现成的jmeter插件,报告也有了~
ps:貌似京东的某团队的接口测试就是jmeter+jenkins

你这种测试,可以考虑结合robotframework来做的,更加简便,也能满足你现在的要求

snake #12 · May 14, 2015 作者

@mic jmeter+jenkins 的我差不多已经整明白,搞出来了。

snake #13 · May 14, 2015 作者

@75281920 方案很多,不管是做自动化,还是做接口测试,RF差不多都是最简单的。Robotframework很容易上手的,好像通用性不是特强吧,你有在Mac下整过Robotframework 么?

我用的 java HTTPclient + testNG

请教下,你对接口返回的值是全部验证吗?还是只验证一个状态?

可以上传到github里,参考一下吗楼主?

提两个小建议:

  1. 对于复杂的结构比较可以自己定义一个类,然后把你期待的值和返回的值都放到这个类对象中进行比较。这样的好处是可读性比较强,而且在你做其他level的测试时可以复用,比如UI driven。
  2. 不知道你们用什么管理case,其实用excel的方式也行,但是不利于统一管理和分享,可以考虑和case管理工具集合起来,这样如果有任何修改也不用在不同的地方进行反复修改了,而且任何人可以更新用例

为何不用requests这个库,方便太多。

snake #19 · May 25, 2015 作者

@sunrise 有空去瞅瞅。

snake #20 · May 25, 2015 作者

@flint 你的建议我会考虑的。

snake #21 · May 25, 2015 作者

@michael_wang 状态是最基本的,会对关键的值校验,如果需要检验全部也是可以的,这个就看需要了。

#20楼 @snake 可以用xml的方式定义结构,属性和默认值注入,按照xml里的节点set attribute,这样不需要改代码就可以生成一个新的类,然后重写他的eq方法,这样就可以比较你想比较的字段。在xml中还可以反射方法,用来初始化。

我也写过python接口测试,比较简单,很多地方没有优化,发出来献丑了:
https://github.com/284772894/httpmat
持续集成一直想去弄,但是就我们公司现在这情况,我只能呵呵。。。。

snake #24 · May 26, 2015 作者

@284772894 能达到效果就行了,我一贯的宗旨是:好用,方便,简单

请问下你的checkpoint怎么定义?类似于直接json对比code为0就为成功?

如何用不同的IP与UA头去点击一个链接

为何大家都用Excel?个人觉得比较臃肿。我目前在用Java开发接口自动化,思路和你一样,不过用虚拟机搭一个小型的Web加一个小数据库,方便实在,输出也可以写到静态页面在web上展示。这样不好吗?

我做过类似的API测试,也是基于Python+Nosetests,,希望这几点对你有用:
1、Excel文件读写可以对比下如下模块:XlsxWriter、xlrd&xlwt、OpenPyXL、Microsoft ExcelAPI。
2、报告可以采用HTML的格式,如HTMLTestRunner,其方便,见下图:

3、测试结果自动推送能不能推送到工作工具,比如:RTX、百度Hi、QQ

谢谢 ,看一看

ride直接做不可以嘛?

您好,我能加你qq吗?有点问题想请教您,我的qq1061611970

简洁胜过复杂--
解析测试数据、构造请求、解析结果这部分都过于复杂。

  1. 解析数据这一块既然Excel模板已有,完全可以封装成get_case_by_name(case_name)、get_case_by_id(case_id), 返回一个dict包含一条测试用例需要用到的数据
  2. 构造请求,同所有人,requests库
  3. 解析结果,json.loads(response.json()),然后遍历dict要容易处理。

花少的时间,搞出简单又好用的东西。

这句太同意了

#27楼 @jet 是呢,excel确实比较臃肿,而且可视化不好,后续维护case个人感觉代价太大,还不如可视化的web界面好一点,不过这样,需要自己搞一个平台才行,不太好嫁接其他的工具吧

好高端,我现在只会用postman+newman+jenkins的组合,python只会皮毛……楼主好腻害

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up