目录
一、为什么要做API接口的单元测试
一个完整的项目,无论是个人的还是公司的,自动化的单元测试是必不可少,否则以后任何的功能改动均可能造成灾难性影响。
1.1 讲一个小故事
假设你正在维护公司的一个项目,这个项目已经开发了几十个 API 接口,但是没有任何的单元测试。
现在你的 leader 让你去修改几个接口并实现一些新的功能,你接到需求后高效地完成了开发任务,然后手动测试了一遍改动的接口和新实现的功能,确保没有任何问题后,满心欢喜地提交了代码。代码上线后出了 BUG,分析原因发现原来是新的改动导致某个旧 API 接口出了问题,因为上线前只对改动的接口做了测试,所以未能发现这个问题。
你的 leader 批评了你,你因为事故记了过,年终绩效评价只能拿个C,奖金受到了影响。
但是如果我们有全面的单元测试,上述情况就有很大概率避免。只需要在代码发布前运行一遍单元测试,受影响的功能立即就会报错,这样就能在代码部署前发现问题,从而避免线上事故。
当然以上故事纯属虚构,说这么多只是希望大家在开发时养成良好的习惯,一是写优雅的代码,二是一定要测试自己写的代码。
1.2 目前存在的问题
现在假设我们有一支团队。
-
团队的现状:
没有API接口测试,后端研发只在接口研发完成时自己用Postman调用一遍本地测试,测试覆盖率极低。
在持续开发过程中,后期开发的接口可能与前期开发的接口复用同一段业务逻辑,改动逻辑代码后,前期开发的接口极大可能报错或失效。
上线一段时间后,由于业务、人员的变更,导致代码没人敢动,生怕影响了业务逻辑,不能持续重构与演进。 -
团队的资源:
团队采用前后端分离的开发方式,产品1人、UI设计师1人、前端2人、后端5人、测试1人。
需要一套高效的合作模式。
1.3 痛点
为了解决以上的问题,我们对API单元测试工具总结了六个需求点:
-
能用
能够通过页面配置,快速生成或批量导入我们开发好的接口定义和入参定义,最好能持续集成。 -
可扩展
接口入参可配置,可自定义Header、Cookie的信息,方便调试接口。 -
测试报告
支持自动化测试,方便的测试集配置方式,能出具测试报告,最好能持续集成。 -
能Mock数据
前端研发人员能根据接口定义,快速配置Mock Server进行并行开发。 -
持续集成
开发人员在合并代码时,自动触发接口测试,验证主流程不受影响。 -
个性化需求
支持前置与后置代码编写,支持不同团队个性化需求。
二、技术选型
2.1 选择标准
我们的需求,找到一款开源、广泛使用、能无缝对接Swagger规范(不用手工定义一个个接口),支持自动化测试流程、对前端支持Mock数据的工具。
2.2 市面上现有的工具
经过对比,发现开源项目中,仅YAPI符合我们的要求,功能覆盖的最多,并且开源支持私有化部署。
三、YAPI介绍
3.1 概览
3.2 核心功能
本章节介绍YAPI的核心功能。
3.2.1 接口创建与导入
接口数据导入:
-
手工导入
在数据管理可快速导入其他格式的接口数据,方便快速添加接口。YApi 目前支持 postman, swagger, har 数据导入。 -
命令行导入
使用yapi-cli工具配置yapi-import.json文件,执行yapi import。 -
定时任务导入
定时任务仅支持Swagger规范数据自动同步。
三种合并模式:
- 普通模式(normal):不导入已存在的接口;
- 智能合并(good):已存在的接口,将合并返回数据的 response,适用于导入了 swagger 数据,保留对数据结构的改动;例如,用户对字段code 添加了mock信息, 当再次数据导入的时候 mock 字段将不会被覆盖
- 完全覆盖(mergin):不保留旧数据,完全使用新数据,适用于接口定义完全交给后端定义, 默认为 normal
3.2.2 接口调试功能
接口运行功能,是用来测试真实接口的,类似『Postman』的功能。
点击运行 tab ,可进入到接口测试页面,首先安装『chrome crossRequest』扩展,才可正常使用此功能。
点击保存按钮可把当前接口保存到测试集,方便下次调试。
接口返回数据验证
接口的返回数据格式为json schema 在接口运行时会对接口返回数据和定义数据格式进行校验。
3.2.3 自动化测试
-
创建测试集合
使用 YApi 自动化测试,第一步需要做得是创建测试集合和导入接口,点击添加集合创建,创建完成后导入接口(同一个接口可以多次导入)。
-
编辑测试用例
编辑请求参数(Mock参数、变量参数)
编写断言脚本 -
调整测试集内接口执行顺序
-
运行自动化测试
在测试列表可以看到每个测试用例的 key,还有 开始测试、报告等功能
点击开始测试会按照 case 定义的参数从上往下一个一个进行测试,如果顺序有问题,可以拖动调整
测试完成之后,点击报告查看该次请求的结果
3.2.3.1 Mock入参
Mock 参数每次请求都会生成随机字符串。
3.2.3.2 参数变量
YApi 提供了强大的变量参数功能,你可以在测试的时候使用前面接口的 参数 或 返回值 作为 后面接口的参数,即使接口之间存在依赖,也可以轻松 一键测试~
Tips: 参数只能是测试过程中排在前面的接口中的变量参数
格式:$.{key}.{params|body}.{path}
例如:现有两个接口,分别是“导航标题”和“文章列表”
文章列表接口需要传参数: 当前标题(id),而这个 id 需要通过 导航标题 的返回值获取,这时应在 文章列表 的参数输入框中根据前者的 key 找到对应 id。
其中 $.
是使用 动态变量 的标志,$.269.params
即表示 key 值为 269 用例的请求参数,$.269.body
即表示 key 值为 269 用例的返回值。
目前 yapi 中的query
、body
、header
和pathParam
的输入参数已经支持点击选择功能。
无需自己填写表达式,只需在弹窗中选择需要展示的表达式即可。
输入选项包括常量,mock数据,在测试集合中也支持变量选择。
具体用法:单击编辑按钮打开表达式生成器,点击需要的数据创建表达式,这里也可以实时查看表达式结果。
3.2.3.3 断言
- assert断言函数
assert(value)
:判断 value 是否为 truth, 例如 assert(1) 通过, assert(0) 不通过,只要 value 不是 null, 0, false 等值验证通过assert.equal(actual, expected)
:判断 actual 是否等于 expected,例如 assert(1, 1)通过assert.notEqual(actual, expected)
:判断 actual 是否不等于 expectedassert.deepEqual(actual, expected)
:假设: actual = {a:1} 是一个对象,即便 expected = {a:1},如果使用 assert.equal 可能也是不相等的,因为在 js 引用的只是对象的一个指针,需要使用 assert.deepEqual 比较两个对象是否相等assert.notDeepEaual(actual, expected)
:深度比较两个对象是否不相等
-
status
http 状态码 -
params
http request params, 合并了 query 和 body -
body
返回 response body -
header
返回 response header -
records
记录的 http 请求信息,假设需要获取 key 为 555 的接口参数或者响应数据,可通过 records[555].params 或 records[555].body 获取 -
log
log(message) 函数,调试时使用,log 信息仅仅在断言失败后打印,失败断言前的信息
3.2.4 测试报告
-
服务端自动化
开始测试功能是在浏览器跑自动化测试,他依赖于浏览器的使用环境。服务端自动化测试功能是在YApi服务端跑自动化测试,不需要依赖浏览器环境,只需要访问 YApi 提供的 url 链接就能跑自动化测试,非常的简单易用,而且可以集成到 jenkins。
-
运行
点击服务端测试,用户访问该 url 就可以获取当前测试用例的所有测试结果。 -
配置通用规则
配置通用规则能够使自动化测试,可以基于通用的规则去控制,无需手动一个一个维护case。
测试报告样例如下图所示:
3.2.5 Mock Server
定义Mock接口
无需单独定义任何Mock接口,YAPI会默认提供全部已导入接口的Mock数据查询接口。
定义Mock返回数据
-
mockjs
基于 json + 注释 定义 mock 数据
-
json-schema(默认方式)
开启 json-schema 功能后,根据 json-schema 定义的数据结构,生成随机数据。
使用Mock接口
- 在代码直接请求 yapi 提供的 mock 地址,不用担心跨域问题。
- 使用本地代理
查询mock接口返回示例如下图所示:
四、在项目中落地应用
4.1 创建项目
每一个后台服务,创建一个对应的YAPI项目,且工程名称保持一致。
4.2 项目配置
项目配置中,主要配置两项:
项目名称要与工程名称一致。
接口基本路径,使用 /api/项目工程名称
4.3 Swagger自动同步
初始化导入全部接口
配置定时任务,按10-30分钟执行一次
合并模式为智能合并
定时任务执行后,会有执行记录
4.4 请求环境配置
-
环境域名必须配置
微服务项目一般配置为网关地址,普通项目直接配置工程地址: -
网关权限验证
支持两种方式,header和cookie。
我本地测试,使用cookie中set关键字为ARCTIC_GATEWAY_SESSION,value取值格式为用户名@test,就可以通过网关权限认证。
大家可以根据自己的项目情况自行设置。
4.5 测试集配置
建议配置一定数量的测试集来保障测试效果。
-
每个测试项目,要创建一个涵盖大部分接口的通用测试集,其中配置如下两条必验规则:
检查HttpCode是否为200。
assert.equal(body.success, true) -
每个功能模块本身的增删改查,为一个小的测试集。
除了httpcode为200、success为true以外,还要配置接口之间的断言。比如插入是否成功、修改是否成功、删除是否成功等。 -
按照业务流程的测试集(可选)
按照产品设计的业务流程配置测试集,比如正向主业务流程、分支业务流程、逆向业务流程等。
4.6 前后端配合
-
接口定义文档输出里程碑
前后端一起定义接口与入参
后端编写接口和相关注解形成Swagger标准文档 -
前端根据UE原型review接口定义与参数定义
是否存在错误或缺失的接口。
是否存在错误或缺失的参数。 -
联调前,后端编写API单元测试用例并自动化
全部接口httpcode必须为200,返回值success必须为true。
每个小功能模块,必须定义增删改查测试集并通过。
五、总结
在团队实际使用过程中,执行力是关键因素,研发经理要保证前后端研发工程师确实认真配置了测试用例,在代码有变化时,测试用例需要一起变化。
这个习惯的养成很重要,初期很不容易,研发经理要进行督促。
在坚持一段时间,团队每个人都在单元测试中获益后,就可以成良好的循环,软件质量一定会上一个台阶。