接口测试是项目测试过程中非常重要的一环,测试的对象是接口,所以提早介入测试,对代码逻辑进行全面验证,就会更早的发现程序的问题。同时,接口测试比UI测试效率更高,并且更容易验证极端和异常的情况。
那么什么是接口测试,以及如何在实际环境中进行接口测试呢?本文手把手教会你接口测试的逻辑和方法。
1.接口测试概念
1.1接口的定义
应用程序编程接口(API Application Programming Interface)是在不同进程,程序或系统之间的通信的代码.API通常基于客户机/服务器模型。有交互的地方都有接口。最常见的跨应用交互协议是HTTP + JSON,其次是网络服务。最常见的后台协议有thrift,dubbo及大量的私有协议。
1.2接口测试的定义
接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关系等。简答的说就是通过URL向服务器或者其他模块等,传输我们想传输的数据,然后看看它们返回的是不是我们预期想要的。
1.3接口测试的重要性
1)越底层发现错误,它的修复成本是越低的。
2)前端随便变,接口测好了,后端不用变,前后端是两拨人开发的。
3)检查系统的安全性,稳定性,前端传参不可信,比如京东购物,前端价格不可能传入-1元,但是通过接口可以传入-1元。
4)如今的系统复杂度不断上升,传统的测试方法成本急剧增加且测试效率大幅下降,接口测试可以提供这种情况下的解决方案。
5)接口测试相对容易实现自动化持续集成,且相对UI自动化也比较稳定,可以减少人工回归测试人力成本与时间,缩短测试周期,支持后端快速发版需求。接口持续
集成是为什么能低成本高收益的根源。
6)现在很多系统前后端架构是分离的,从安全层面来说:(1),只依赖前端进行限制已经完全不能满足系统的安全要求(绕过前面实在太容易),需要后端同样进
行控制,在这种情况下就需要从接口层面进行验证。(2)中,前后端传输,日志打印等信息是否加密传输也是需要验证的,特别是涉及到用户的隐私信息,如身
份证,银行卡等。
总之接口测试是保证高复杂性系统质量的内在要求和低成本的经济利益的驱动作用下的最佳解决方案,接口测试是一个完整的体系,也包括功能测试,性能测试。
2.怎么做接口测试
2.1接口测试的准备工作
1)是否有接口文档?接口文档内容有哪些?
o接口文档五要素:接口地址,接口请求的方式,是否有请求参数(参数相关属性),返回参数说明(参数相关属性),返回结果样例;
o如果没有接口文档,到功能测试阶段,需要自己抓包,抓包工具如提琴手等。
2)明确接口测试流程。
o主要的流程包括:接口文档 - 接口测试计划,方案 - 接口测试用例(评审) - 执行 - 集成到Jenkins - 接口反馈
3)分析每一个接口:标题,URL,参数(含义,可选/必选,格式,类型等等),响应数据来源及数据量。
4)分析实际可做接口测试的测试点。
o单一接口功能的测试主要测试返回的数据结构是否和接口文档给出的一致;
o接口的正常功能是否完成;
o接口的参数检查测试,接口的异常测试;
o多接口组合测试,实际上是在测试一个业务流;
o在测试过程中一次调用多个接口。
2.2编写测试用例
编写一个覆盖率全面的用例,我们可以考虑以下的测试点:
一般我们能把上面的测试点都覆盖了,用例就差不多了。
2.3接口测试过程
根据开发人员提供的接口访问地址,入参格式,请求格式,进行接口请求数据拼接,并查看返回结果及返回报文,响应时间,检查返回的Json内容是否符合接口定义规范,是否符合预期的返回结果。
总的来说可以划分为三个部分:
o发起接口请求(请求)
o解析接口响应(响应)
o检查接口测试结果(确认)
2.4接口测试方法
如何通过接口向服务器发送请求数据,并接收返回的数据呢一般我们用以下的测试工具?
1)WebService的接口:是用皂协议包装后用HTTP运输,请求报文和返回报文都是XML格式的,我们在测试的时候都用通过工具才能进行调用,测试可以使用的工具有了SoapUI, JMeter的,LoadRunner的等。
2)Http api接口:直接用http协议运输,通过路径来区分调用的方法,请求报文都是键值形式的,返回报文一般都是json串,有得和后等方法,这也是最常用的两种请求方式。可以使用的工具有邮差,RESTClient实现,的JMeter,LoadRunner的等。
当然我们也可以自编接口测试脚本在测试脚本过程中,应注意:
1)不断调试脚本;
2)添加逻辑控制,对脚本内的数据进行参数化(包括:前置条件,测试步骤及测试数据);
3)添加用例里的预期结果。
最后,执行测试和脚本,并对执行结果进行分析包括:错误分析,响应结果分析,响应时间分析等等。
3.自动化
3.1自动化框架选择
市面上有许多接口自动化的框架,我们这次讲的是我所用的一套接口自动化框架。
python+requests+robotframework
选取robotframework主要原因是:
1)使用关键字的机制,更容易上手
2)提供了RIDE,对于不熟悉编码的人来说比较友好
3)能够精细的控制关键字的范围
4)日志和报告非常好
5)使用变量文件的机制来描述不同的环境
6)丰富的关键字库
7)内置变量
3.2框架搭建
蟒蛇和请求库的安装在此就不累赘了,我们介绍robotframework的安装,由于最近RIDE1.7.3的版本改进,RIDE这个版本对高版本的wxPython的兼容很好,python3.6及以上版本都可以顺利运行。RIDE所以我们可以采用在线安装robotframework:
pip install robotframework #在线安装RF,安装好了输入robot命令验证一下,结果报错显示缺少参数则说明安装成功
pip install robotframework-ride #在线安装RIDE,相关wxpython等相关依赖会自行安装的,安装成功后在python安装目录下Scripts目录里面有一个ride.py文件,双击运行它,如下:
这样我们就把框架搭建好了。
3.3方法的封装
由于不同公司,不同开发者的接口规范不一样,所以我们一般会用蟒二次封装一些常用方法,使之更适合我们请求接口,获取返回值;方便后续再robotframework上编写自动化测试用例常见的二次封装有如下例子:
1)请求方法和返回数据的封装,可以参考以下代码:
#api请求方法封装,method 枚举值为:POST、GET、PUT、DELETE
def Senddata(self, url, data, method):
print ('*************** Senddata 函数开始 ***************', method)
try:
if method == "POST":
print('url:', url)
if data == "nodata":
resp = requests.post(url, data=commApi.data, headers=commApi.headers, timeout=30, verify=False)
else:
datastr = eval(data)
resp = requests.post(url, data=json.dumps(datastr), headers=commApi.headers, timeout=30,
verify=False)
elif method == "PUT":
if data == "nodata":
resp = requests.put(url, data=commApi.data, headers=commApi.headers, timeout=30, verify=False)
else:
datastr = eval(data)
resp = requests.put(url, data=json.dumps(datastr), headers=commApi.headers, timeout=30, verify=False)
commApi.res = resp.json()
elif method == "DELETE":
resp = requests.delete(url, headers=commApi.headers, timeout=30, verify=False)
commApi.res = resp # 删求成功无数据返回,无需要json转码请求结果
if int(resp.status_code) != 200:
commApi.res = resp.json() # 删求失败有数据返回,需要json转码请求结果
else:
if data == "nodata":
resp = requests.get(url, headers=commApi.headers, timeout=30, verify=False)
else:
datastr = eval(data)
resp = requests.get(url, params=datastr, headers=commApi.headers, timeout=40, verify=False)
commApi.res = resp.json()
commApi.code = resp.status_code
resp.raise_for_status() # 如果响应状态码不是 200,就主动抛出异常
except requests.RequestException as e:
print(e)
return commApi.res
else:
return commApi.res
#设置请求头
def setHeader(self,account=None,password=None):
print('*************** setHeader 函数开始 ***************')
if account == None and password == None:
commApi.headers = {'Content-Type': 'application/json'}
else:
Authorization = 'Basic %s:%s'%(account,password)
print ('Authorization:',Authorization)
commApi.headers = {'Content-Type': 'application/json', 'Authorization': Authorization}
#获取接口返回数据(json格式)
def getRes(self):
print('*************** getRes 函数开始 ***************')
return commApi.res
#检查状态返回码
def Check_code(self, code='200'):
print('*************** Check_code 函数开始 ***************')
assert (commApi.code == int(code))
#检查接口返回数据
def Check_response(self, result, code, message=None, checkData=None):
print('*************** Check_response 函数开始 ***************')
backdata = commApi.res
if result == "success":
assert (backdata[u'code'] == int(code))
elif result == "failed":
assert (backdata[u'message'] == message and backdata[u'code'] == int(code))
return backdata
2)获取随机数据方法的封装,可以参考如下封装方式:
3.4接口框架设计 - 数据与接口分离
分层原则:【分层目标:接口数据和接口业务分离】
可再细分为:
1. 项目接口分层:具体要实施接口自动化的工品的主目录。其中,项目主目录中,按分层思想,又可根据接口功能作为二级目录。
目录结构规范:
模块名:project name
子模块名:folder name
接口名:suite name
用例名:case name
如:分类大致思路如此,如类别之间有更细的分类加入即可,如sdk有platform区分、push api有v2和v3版本之分、模块下可以多个自模块等,总之按照树形结构展开符合逻辑即可。
2. 接口业务分离:不同接口模块下,又可根据子功能的不同,划分成不同接口主要又包含两部分,一部分为接口业务关键字,通常一个接口下,可以根据测试的业务不同,定义多个不同的关键字。另一部分就是接口功能用例,接口用例下仅需填测试数据即可。通常不同的用例存放不同的测试数据,即业务关键字的入参,业务关键字根据接收到不同测试数据而去自动执行对应的业务流程。通常将具体的一组动作序列封装一个业务关键字,测试用例中之所以以存放测试数据的设计核心就是在于将测试业务与测试数据分离。因为通常测试过程中,一个业务关键字的动作序列不会经常变更,需要变更的是测试数据,通常不同的测试数据,会导致业务关键字的产生的结果不同。
3. 公共方法数据分离:包括三部分,公共方法(公共),项目配置文件(配置),数据构造文件(TestData.py)其中:
公共方法:主要提供各个不同项目接口之间都会调用到的一些公共方法,如接口请求,接口数据校验、接口统计等,详情可以看3.3 请求方法和返回数据的封装。
主配置文件:主要存储接口在各个不同环境下(通常一个产品,开发完成后,都需要在测试环境验证通过后,才可发布到线上环境,这里所说的不同环境指的就是测试环境、线上环境)的访问地址,通常做法可在业务关键字编写脚本时,将接口访问地址通过变量来控制,然后此变量访问主配置文件对应的接口地址即可,通常接口环境分定义为测试环境下的接口访问地址、预发布环境接口地址、线上接口环境地址等。
数据构造文件:数据控制文件的设计核心在于,在变量文件中定义构造数据的函数方法,然后将方法的返回值赋给一个变量,在具体的接口引用该变量。详情可以看3.3 获取随机数据方法的封装。
3.5 robotframework用例编写
参考3.4的分层思想我们可以编写出以下用例:
4.持续集成
本文介绍的是使用詹金斯做持续集成
1)安装插件
进入詹金斯主页面,系统管理 - 管理插件 - 可选插件;在过滤栏输入“机器人”,选择安装如下图的插件
2)新建工程
新建,输入一个需要创建的任务名称,并选择“构建一个自由风格的软件项目”,然后点击OK
3)源码管理,根据项目情况选择;我们选择GIT中,填写对应的信息;
4)构建触发器
o民意调查SCM:定时检查源码变更
o定期建造:周期进行项目构建
5)构建
执行robotframework用例关键语句:pybot -d用例地址
6)构建后操作
o选择“发布机器人框架测试结果”
机器人输出目录填一个本地路径,要根据你的输出文件放在哪里,可以不填
构建结果的阈值测试用例执行成功率和通过率的设置,如80%和100%
o选择“可编辑的电子邮件通知”
* Project Recipient List这是一个以逗号(或者空格)分隔的收件人邮件的邮箱地址列表。允许您为每封邮件指定单独的列表。
7)应用保存
o创建成功
8)自动构建
o创建成功的工程会根据你制定的时间自动构建,执行自动化用例。
除了每日的定时触发自动化测试用例外,我们还可以让用例与相应的模块服务构建的工作相关链,这样模块代码有更新,部署到环境后,就会自动跑一遍自动化用例,测试结果可以更及时的对这次代码的质量进行评估,是否达到测试准入资格。