本文内容学习于《自动化测试实战宝典》 - 周金剑
接口测试作为测试金字塔结构的中间层,有低成本、高回报的优势; 在实际的项目中有助于验证服务之间数据协同和数据交互,对降低测试成本和提高测试效率有极大的作用; 可以说,接口测试是业务功能测试前置的助推器;
1. 接口测试扫盲
1.1 接口的本质
- 接口声明了一组能力,但它自己并没有实现这个能力,它只是一个约定;
- 它涉及的交互双方,一方实现接口,一方使用接口;
- 双方并不相互依赖,只是通过接口进行交;
举个简单的栗子:各种常用的电器插口,基本上只有一两口或者三口;因为,所有的制造商都是按照这个规范来设定的,所以,当你使用时,就会很方便,但凡有一个厂商生产了四个口或者一个口的,那就打破了这份规定,另一方就无法使用;
- 官方定义:接口的本质就是抽象出一些共性的方法形成一种约定或规范;
- 通俗来说,就是一种约定,一种契约精神,你给我什么信息,我帮助你做什么事情,返回什么结果,双方都准守这个契约做事;
- 使用接口,可以有效降低程序与程序或者程序与模块之间的耦合性;
1.2 接口的类别
在了解接口的类别之前,我们需要思考一下:接口在系统中为何要存在?
- 随着软件开发越来越大型化、团队化、模块化,越来越不可能一个人从头做到尾,总有人在你后面为你提供数据,有人在你前面调用你实现的一些功能,有人在你下面提供基础类库、常见操作的抽象;
- 人和人之间的合作靠约定,程序员和程序员之间的协作靠的就是接口;
- 按整体来划分:
- 硬件设施层面的接口:
- 例如 HDMI(High Definition Multimedia Interface,高清多媒体接口),同样用于双方对接,不需要关注双方的具体实现;
- 你可以回想一下,HDMI 的输入设备可能是计算机、电视盒、游戏机等,输出设备可以是显示器、投影仪等;
- 软件程序交互的接口:
- 俗称应用程序接口(Application Programming Interface,API):
- API 是外部系统与内部系统以及各个子系统之间交互的纽带;
- 这条纽带通过约定好的协议进行数据的传递、交互;
- 从广义上来讲接口就是客户端与后台服务间的协议、插件间通信的接口、模块间的接口,或者小到一个类提供的方法,都可以理解为接口;
- 程序内部的接口:
- 程序内部交互的接口,如方法与方法之间、模块与模块之间协同完成某一个场景功能所需的接口;
- 简单来说,就是内部系统进行调用的一种接口;
- 如,一个论坛有登录模块和发帖模块等,用户需要发帖就必须先登录,那么可以让登录模块提供一个登录接口,在发帖之前先调用登录接口;
- 系统对外的接口:
- 一般泛指第三方组织提供的服务接口;
- 你想从别的网站获取资源或操作信息,别人肯定不会给你提供数据库信息;
- 比如,一些应用程序集成支付功能,可以调用微信支付或者支付宝支付接口,此时对于微信和支付宝来说,就是将支付接口对外开放给第三方组织,而支付接口对于第三方组织而言,就是微信、支付宝系统对外提供的接口;
第一方:本部门、本项目; 第二方:本公司跨部门、跨团队的项目; 第三方:其他组织、外部公司;
1.3 接口测试
- 接口测试就是通过测试不同情况下的入参和与之相应的出参,来判断接口是否符合或满足相应的功能性、安全性要求;
- 测试的重点:
- 检查数据的交换、传递;
- 控制管理过程;
- 系统间的相互逻辑依赖关系;
- 测试策略上来看,接口测试是一套完整的测试体系:
- 接口功能测试;
- 接口性能测试;
- 接口稳定性测试;
- 接口安全性测试;
1.4 接口交互示意图
1.5 接口测试的关注点
- 整体来讲,接口测试的关注重点主要分两类:
- 综述,接口测试需要注意的事项为:
- 检查接口返回的数据是否与预期结果一致;
- 检查接口的容错性,例如,传递数据的类型错误时是否可以处理;
- 接口参数的边界值,例如,传递的参数足够大或为负数时,接口是否可以正常处理;
- 接口的性能,接口处理数据的时间也是测试的一个重点,牵扯到内部算法与代码的优化;
- 接口的安全性,如果是外部接口,这点尤为重要;
1.6 接口测试的介入时机
- 展开接口测试之前,需要了解清除,待测接口在系统中如何通信、图和传递数据、接口测试的基本流程和实现原理;
1.7 接口测试的根本目标
- 一个好的接口测试项目可以从如下八个方面进行考虑:
- 业务功能覆盖是否完整;
- 业务规则覆盖是否完整;
- 参数验证是否达到要求(边界、业务规则);
- 接口异常场景覆盖是否完整;
- 接口覆盖率是否达到要求;
- 代码覆盖率是否达到要求;
- 性能指标是否达到要求;
- 安全指标是否达到要求;
- 一个好的接口测试项目至少满足三点业务赋能要求:
- 线下冒烟测试,提高回归效率:
- 在测试环境中,保证新增功能的正确性,原有接口的批量回归,保证原有借口不被修改“坏”;
- 线上巡检测试,提升线上问题的探测能力:
- 在生产环境中,保证接口层面服务的可用性,功能的正确性,通过每日接口线上巡检,保证服务“挂掉”或出现异常时,能及时发现;
- 做到“效率+质量”的双向平衡:
- 以较少的人力和时间成本投入,结合当下的团队环境,最大限度的提高产品质量和用户体验;
2. 开展接口测试的基本流程
- 接口测试框架的选型:
- 选择 Robot Framework 这款通用型自动化测试工具;
- Robot Framework 是用于验收测试和验收测试驱动开发(ATDD)的自动化测试框架;基于 Python编写,提供跨平台支持;
- 确定接口测试的范围:
- 通常并不是项目中所有的接口都需要实现测试自动化的,至少并不是在一开始就要把所有接口全部实现;
- 需要根据接口在业务中的重要程度挑选各个阶段的接口范围,以确定接口的优先级;
- 分析接口的功能需求:
- 明确接口在业务场景中起到的作用是什么;
- 确保接口在做正确的事情,以及有效的进行测试;
- 接口文档的获取:
- 通过接口文档,明确接口各入参字段的作用和相应出参信息;
- 常见的接口文档形式:
- Swagger(一款 Restful 接口,基于 Yaml、Json 语言的文档在线自动生成、代码自动生成工具);
- YApi(一款可视化在线接口管理平台);
- CrapApi(一款多人协作的在线接口管理平台);
- Wiki;
- Word;
- 等;
- 接口测试用例设计:
- 按照接口文档的约定信息,以及结合接口在业务需求中的作用,编写接口测试用例;
- 大致分为四步:接口入参 --> 发起请求 --> 响应输出 --> 结果校验;
3. 接口测试用例设计
3.1 三类对象抽象模型
3.2 接口测试三层模型
- 类比三类对象抽象模型可以将三个环节分别对应为:
- 接口输入;
- 接口逻辑处理;
- 接口输出;
3.3 接口输入用例设计
- 输入环节最重要的就是入参部分:
- 针对输入部分的用例设计,可以按照参数类型进行设计;
- 就接口而言,常用的参数类型有:
- 数值类型(int、long、float、double 等);
- 字符串类型;
- 列表(数组)或链表;
- 字典(结构体)或集合;
- 结构体是一些元素的集合,里面包含的元素可以是数值、字符串、数组(列表)或链表;
- 数值类型:
- 规则:
- 等价类:取值范围内、取值范围外;
- 边界法:
- 取值范围边界(边界最大值、边界最小值、边界最大值+1、边界最小值-1);
- 数据类型边界(最大值、最小值、超过或不在数据类型取值范围内);
- 特殊值:0、负数等;
- 遍历法:取值范围内的所有数值;
- 实例:一个用于检查任务是否有效的接口 TaskCheck.checkTask(int taskID),其中 taskID 的有效取值范围是 1~20;
- 1~20 范围内和范围外值:1,5,10,20,30;
- 1~20 的边界:0,1,20,21;
- 数值类型的边界值:int 最小值(-2147483648)和最大值(2147483647);
- 特殊值:-1, 0;
- 遍历值:1,2,3,……,20;
在实际项目中,当参数取值范围过大时,不必遍历每个值,可以结合等价类选取一些关键典型的值进行遍历,可根据业务需求来定;
数值类型常见问题:
- 特殊值处理不当导致程序异常退出;
- 类型边界溢出;
- 取值范围外的值未返回正确的错误信息等;
- 字符串类型:
- 规则:从字符串长度和字符串内容两方面来考虑:
- 字符串长度:
- 等价类:字符串取值范围内、取值范围外;
- 边界法:
- 特殊值:空字符串;
- 字符串内容:
- 特定类型:英文字符,中文字符,大小写,中英文组合等;
- 特殊字符:如 <>,$,@ 等;
- 敏感字符:如“台独”,“色情”等敏感字符;
- 实例:视频网站发弹幕接口为 VideoService.sendBullet(String xxx),发送弹幕最大长度为 15 个字符,在设计用例时可以考虑:
- 弹幕字符长度为 15 个字符,大于 15 个字符,小于 15 个字符的情况;
- 15 个英文字符,15 个中文字符,15 个中英文组合字符;
- 边界值 String 的最大长度;
- 特殊值:空字符串、None、Null;
- 非字符串类型:数字、非数字、字符数字组合;
- 如果输入的内容其他用户是可见的,则还需考虑敏感字符是否能被正常过滤;
字符类型常见问题:
- 传入非特定类型导致程序异常退出;
- 超长字符未进行处理,导致存储,显示等异常;
- 其他用户可见设置的敏感字;
- 数组或链表类型:
- 规则:用例设计可以从数组或链表中元素个数和元素内容两方面考虑:
- 数组或链表元素个数:
- 等价类:数组或链表取值范围内、取值范围外;
- 边界值:规定元素范围边界、元素个数边界;
- 特殊值:空数组或空链表;
- 数组或链表元素内容:
- 实例:批量提交任务的接口为 submitTask(int[] taskID),数组最大接收长度为 10 个,在进行用例设计时可以考虑:
- 正常取值:提交的任务 taskID 个数分别为 1,3,5,8,10;
- 边界值:0,1,10,11,请求允许的最大值和最小值;
- 特殊值:0 或空列表;
- 合法任务 taskID 和不合法任务 taskID;
- 重复的 taskID 元素;
数组或链表常见问题:
- 0 个元素导致程序异常退出;
- 当存在重复元素时未去重导致结果异常等;
3.4 接口逻辑用例设计
- 接口逻辑中可以体现接口设计的健壮性;
- 在用例设计时,一般从:约束条件、操作对象、转态转换和时序处理等几个方面来考虑;
- 约束条件分析:
- 规则:
- 数值限制:常见的有分数限制,金币约束限制,等级限制等;例如,兑换 Q 币活动要求等级为 3 且积分 > 1000 分的用户才可以参与;
- 状态限制:常见的有登录状态;例如,同步用户信息需要先登录账号;
- 关系限制:常见的有绑定家人关系、好友关系等;例如,家人防骗功能只允许查询绑定家人的来电信息;
- 权限限制:常见的有管理员、普通用户权限等;例如,后台登录限制了具有管理员权限的账号才可以成功登录;
- 实例:兑换 10 Q 币需要 500 积分,但积分不足,只有 30 分,此时在前端界面上兑换按钮显示为灰色且无法单击的状态;
- 正常来讲用户是无法进行兑换操作的,但是由于兑换功能本质上是调用后端的一个接口,如果饶过页面按钮的限制,直接调用后台接口兑换,是否可以兑换?预期当然是不可以兑换的,因此积分限制就需要针对接口进行测试;
- 时间约束:只允许在 22:00 之前进行兑换;
- 数值约束:超过 500 积分,且限量为 10;
- 状态约束:登录账号;
约束条件常见的问题有:
- 操作对象分析:
- 操作对象就是字面意思,被操作的对象;
- 主要针对的是合法与不合法进行操作;
- 例如,用户绑定电话号码,电话号码就是操作对象,并且其中话费和流量也是操作对象;
操作对象常见的问题:
- 用户可以访问非权限的其他用户信息,敏感信息,从而利用这些信息谋取利益;
- 状态转换分析:
- 规则:
- 被测逻辑可以抽象成状态,可以根据功能从一个状态切换到另一个转态;
- 若打乱这个次序,从一个状态切换到另一个不在它下一状态集中的状态,那么逻辑就会被打乱,就会出现逻辑问题;
- 实例:从某状态到新状态,依赖于转换接口。而对于某转换接口,其输入状态是确定的,比如 Fun23,这个函数只能把状态 2 转换为状态 3,而不能把状态 1 装换为状态 3,测试点:
- 状态为 2 时,调用接口 Fun23(),状态转换到状态 3;
- 状态为 1 或 3 时,调用接口 Fun23(),状态不能转换;
状态转换常见问题:
- 可通过特殊操作达到原本不能直接到达的状态,从而谋取利益;
- 时序处理分析:
- 规则:
- 在复杂的活动中,一系列操作按照指定的顺序依次执行,才能得到预期结果;
- 在接口测试中,需要考虑如果不按照时序执行,是否会出现问题;
- 实例:客户端数据同步是由客户触发进行的,用户无法干预期间的同步。
- 后台有 3 个接口:登录获取用户 ID,上报本地数据,上报本地冲突。三个接口需要依次调用执行,才能完成同步。在接口测试中可以考虑打乱上述接口的执行顺序去执行会出现怎么样的结果,是否会出现异常。
- 例如,获取用户 ID 后不上报本地数据而直接上报本地冲突;
时序处理常见问题:
- 非顺序执行后,数据出现异常,可能还会出现程序未知异常;
- 通过打乱时序顺序,获取利益。
3.5 接口输出用例设计
- 就是对接口返回的结果进行分析,并断言返回的内容是否符合预期;
- 针对输出响应码:
- 接口处理正确的结果可能只有一个,但是错误异常返回结果有很多种情况;
- 实例:已知某一提交任务接口返回码定义:
ERC_SUCC = 0, // 默认返回值:成功
ERC_FAILED = 1, // 服务器错误:其它问题;
ERC_TASK_INVALID = 2, // 无效任务
ERC_RULE_INVALID = 3, // 无效规则
……
- 可以通过覆盖各类返回码来构造挖掘出更多的测试场景;
常见的返回码问题:
- 错误码前端处理不足,导致前端异常;
- 错误码提示处理不当,导致用户直接看到晦涩的错误码;
错误提示不当,导致用户不知道哪里出了问题;
-
针对输出关键字段:
- 对响应输出的关键性字段进行断言;
- 例如:获取用户的关注列表,需要先调用用户信息接口,并从输出中获取用户 userId,通过 userId 来查询该 userId 关注的列表信息;
- 针对用户接口信息, userId 就是输出的关键字段,需要重点检查 userId 用户信息的输出是否有效;
-
针对接口超时:
- 若,接口没有返回值,对接口超时后的处理不当,会出现以下的问题:
- 未进行超时处理,导致整个流程阻塞;
- 超时后又收到接口返回,导致逻辑出现错乱。、
3.6 其他部分用例设计
3.7 一个完整的栗子
- 实例:某模块提供了一个用户请求任务接口供其他模块调用,请求任务接口参数定义为:
- 针对接口输入进行用例设计
- 参数 detailText 为字符串类型,接口测试用例设计可以从如下几方面考虑:
- 正常长度范围:如“请单击提交”;
- 长度边界:提示文本只保留 1 个字节长度或提示文本超过显示范围;
- 特殊值:提示文本留空;
- 特殊类型:中文字符、英文字符、数字等;
- 特殊字符:/r/t、><、@ 等;
- 参数 buttonText 为字符串类型,与 detailText 类似;
- 参数 taskID 为整型,接口测试用例设计可以从如下几方面考虑:
- ID 正常取值范围:1、5、10、20、30、35;
- ID 取值范围以外:-1,0,36,100;
- 数据类型边界:-2147483648,2147483647;
- 特殊值:0,-1 等;
- 遍历法:1,2,3,……,35 对应每种不同的 ID;
- 参数 requestType 为整型,和 taskID 类似;
- 针对逻辑处理进行用例设计
- 针对输出进行用例设计
- 请求任务接口返回的数据只有任务完成状态:
- 完成任务(未知状态当做完成状态返回);
- 未完成任务;
- 从返回状态可以考虑用例设计有:
- 请求未完成的场景模拟;
- 请求完成的场景模拟;
- 请求未知的场景模拟;
- 从接口调用返回时间的角度分析:
- 请求后快速返回;
- 请求后很长时间才返回;
- 请求后不返回结果;
4. 环境依赖安装
-
大多数互联网后端应用服务采用 HTTP 通信; -
RobotFramework 是一个通用型的关键字测试框架,本身不具备任何测试能力; -
所以基于 Robot Framework 框架开展 HTTP 接口测试需要安装的第三方依赖库为: -
安装命令: pip install requests
pip install robotframework-requests
pip install robotframework-httplibrary
|