1.接口测试概念
1.1接口的定义
1.2接口测试的定义
1.3接口测试的重要性
· 越底层发现错误,它的修复成本是越低的。
· 前端随便变,接口测好了,后端不用变,前后端是两拨人开发的。
· 检查系统的安全性,稳定性,前端传参不可信,比如京东购物,前端价格不可能传入-1元,但是通过接口可以传入-1元。
· 如今的系统复杂度不断上升,传统的测试方法成本急剧增加且测试效率大幅下降,接口测试可以提供这种情况下的解决方案。
· 接口测试相对容易实现自动化持续集成,且相对UI自动化也比较稳定,可以减少人工回归测试人力成本与时间,缩短测试周期,支持后端快速发版需求。接口持续集成是为什么能低成本高收益的根源。
· 现在很多系统前后端架构是分离的,从安全层面来说:(1),只依赖前端进行限制已经完全不能满足系统的安全要求(绕过前面实在太容易),需要后端同样进行控制,在这种情况下就需要从接口层面进行验证。(2)中,前后端传输,日志打印等信息是否加密传输也是需要验证的,特别是涉及到用户的隐私信息,如身份证,银行卡等。
2.怎么做接口测试
2.1接口测试的准备工作
1)是否有接口文档?接口文档内容有哪些?
o 接口文档五要素:接口地址,接口请求的方式,是否有请求参数(参数相关属性),返回参数说明(参数相关属性),返回结果样例;
o 如果没有接口文档,到功能测试阶段,需要自己抓包,抓包工具如提琴手等。
2)明确接口测试流程。
o 主要的流程包括:接口文档- 接口测试计划,方案 - 接口测试用例(评审) - 执行 - 集成到
3)分析每一个接口:标题,URL,参数(含义,可选/必选,格式,类型等等),响应数据来源及数据量。
4)分析实际可做接口测试的测试点。
o 单一接口功能的测试主要测试返回的数据结构是否和接口文档给出的一致;
o 接口的正常功能是否完成;
o 接口的参数检查测试,接口的异常测试;
o 多接口组合测试,实际上是在测试一个业务流;
o 在测试过程中一次调用多个接口。
2.2编写测试用例
2.3接口测试过程
· 总的来说可以划分为三个部分:
o 发起接口请求(请求)
o 解析接口响应(响应)
o 检查接口测试结果(确认)
2.4接口测试方法
· WebService的接口:是用皂协议包装后用HTTP运输,请求报文和返回报文都是XML格式的,我们在测试的时候都用通过工具才能进行调用,测试可以使用的工具有了SoapUI, JMeter的,LoadRunner的等。
· Http api接口:直接用http协议运输,通过路径来区分调用的方法,请求报文都是键值形式的,返回报文一般都是json串,有得和后等方法,这也是最常用的两种请求方式。可以使用的工具有邮差,RESTClient实现,的JMeter,LoadRunner的等。
· 不断调试脚本;
· 添加逻辑控制,对脚本内的数据进行参数化(包括:前置条件,测试步骤及测试数据);
· 添加用例里的预期结果。
3.自动化
3.1自动化框架选择
python+requests+robotframework
· 使用关键字的机制,更容易上手
· 提供了RIDE,对于不熟悉编码的人来说比较友好
· 能够精细的控制关键字的范围
· 日志和报告非常好
· 使用变量文件的机制来描述不同的环境
· 丰富的关键字库
· 内置变量
3.2框架搭建
pip install robotframework #在线安装RF,安装好了输入robot命令验证一下,结果报错显示缺少参数则说明安装成功
pip install robotframework-ride #在线安装RIDE,相关wxpython等相关依赖会自行安装的,安装成功后在python安装目录下Scripts目录里面有一个ride.py文件,双击运行它,如下:
这样我们就把框架搭建好了。
3.3方法的封装
· 请求方法和返回数据的封装,可以参考以下代码:
#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
· 获取随机数据方法的封装,可以参考如下封装方式:
3.4接口框架设计 - 数据与接口分离
1. 项目接口分层:具体要实施接口自动化的工品的主目录。其中,项目主目录中,按分层思想,又可根据接口功能作为二级目录。
2. 接口业务分离:不同接口模块下,又可根据子功能的不同,划分成不同接口主要又包含两部分,一部分为接口业务关键字,通常一个接口下,可以根据测试的业务不同,定义多个不同的关键字。另一部分就是接口功能用例,接口用例下仅需填测试数据即可。通常不同的用例存放不同的测试数据,即业务关键字的入参,业务关键字根据接收到不同测试数据而去自动执行对应的业务流程。通常将具体的一组动作序列封装一个业务关键字,测试用例中之所以以存放测试数据的设计核心就是在于将测试业务与测试数据分离。因为通常测试过程中,一个业务关键字的动作序列不会经常变更,需要变更的是测试数据,通常不同的测试数据,会导致业务关键字的产生的结果不同。
3. 公共方法数据分离:包括三部分,公共方法(公共),项目配置文件(配置),数据构造文件(TestData.py)其中:
**公共方法**:主要提供各个不同项目接口之间都会调用到的一些公共方法,如接口请求,接口数据校验、接口统计等,详情可以看3.3 请求方法和返回数据的封装。
**主配置文件**:主要存储接口在各个不同环境下(通常一个产品,开发完成后,都需要在测试环境验证通过后,才可发布到线上环境,这里所说的不同环境指的就是测试环境、线上环境)的访问地址,通常做法可在业务关键字编写脚本时,将接口访问地址通过变量来控制,然后此变量访问主配置文件对应的接口地址即可,通常接口环境分定义为测试环境下的接口访问地址、预发布环境接口地址、线上接口环境地址等。
**数据构造文件**:数据控制文件的设计核心在于,在变量文件中定义构造数据的函数方法,然后将方法的返回值赋给一个变量,在具体的接口引用该变量。详情可以看3.3 获取随机数据方法的封装。
3.5 robotframework用例编写
4.持续集成
· 安装插件
· 新建工程
· 源码管理,根据项目情况选择;我们选择GIT中,填写对应的信息;
· 构建触发器
o 民意调查SCM:定时检查源码变更
o 定期建造:周期进行项目构建
· 构建
· 构建后操作
o 选择“发布机器人框架测试结果”
*机器人输出目录填一个本地路径,要根据你的输出文件放在哪里,可以不填
*构建结果的阈值测试用例执行成功率和通过率的设置,如80%和100%
o 选择“可编辑的电子邮件通知”
* Project Recipient List这是一个以逗号(或者空格)分隔的收件人邮件的邮箱地址
列表。允许您为每封邮件指定单独的列表。
· 应用保存
o 创建成功
· 自动构建
o 创建成功的工程会根据你制定的时间自动构建,执行自动化用例。