目录

一、为什么要做API接口的单元测试

一个完整的项目,无论是个人的还是公司的,自动化的单元测试是必不可少,否则以后任何的功能改动均可能造成灾难性影响。

1.1 讲一个小故事

假设你正在维护公司的一个项目,这个项目已经开发了几十个 API 接口,但是没有任何的单元测试。
现在你的 leader 让你去修改几个接口并实现一些新的功能,你接到需求后高效地完成了开发任务,然后手动测试了一遍改动的接口和新实现的功能,确保没有任何问题后,满心欢喜地提交了代码。代码上线后出了 BUG,分析原因发现原来是新的改动导致某个旧 API 接口出了问题,因为上线前只对改动的接口做了测试,所以未能发现这个问题。
1
你的 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 市面上现有的工具

2_resize-1659940023468

经过对比,发现开源项目中,仅YAPI符合我们的要求,功能覆盖的最多,并且开源支持私有化部署。

三、YAPI介绍

3.1 概览

3_resize

3.2 核心功能

本章节介绍YAPI的核心功能。

3.2.1 接口创建与导入

4-1659940678452
接口数据导入:

  • 手工导入
    在数据管理可快速导入其他格式的接口数据,方便快速添加接口。YApi 目前支持 postman, swagger, har 数据导入。

  • 命令行导入
    使用yapi-cli工具配置yapi-import.json文件,执行yapi import。

  • 定时任务导入
    定时任务仅支持Swagger规范数据自动同步。

5-1659940697506
三种合并模式:

  • 普通模式(normal):不导入已存在的接口;
  • 智能合并(good):已存在的接口,将合并返回数据的 response,适用于导入了 swagger 数据,保留对数据结构的改动;例如,用户对字段code 添加了mock信息, 当再次数据导入的时候 mock 字段将不会被覆盖
  • 完全覆盖(mergin):不保留旧数据,完全使用新数据,适用于接口定义完全交给后端定义, 默认为 normal

3.2.2 接口调试功能

6-1659941004800
接口运行功能,是用来测试真实接口的,类似『Postman』的功能。
点击运行 tab ,可进入到接口测试页面,首先安装『chrome crossRequest』扩展,才可正常使用此功能。
点击保存按钮可把当前接口保存到测试集,方便下次调试。

7-1659941004800
接口返回数据验证
接口的返回数据格式为json schema 在接口运行时会对接口返回数据和定义数据格式进行校验。

3.2.3 自动化测试

  1. 创建测试集合
    使用 YApi 自动化测试,第一步需要做得是创建测试集合和导入接口,点击添加集合创建,创建完成后导入接口(同一个接口可以多次导入)。
    8-1659941244761
    9-1659941244762

  2. 编辑测试用例
    编辑请求参数(Mock参数、变量参数)
    编写断言脚本

  3. 调整测试集内接口执行顺序

  4. 运行自动化测试
    在测试列表可以看到每个测试用例的 key,还有 开始测试、报告等功能
    点击开始测试会按照 case 定义的参数从上往下一个一个进行测试,如果顺序有问题,可以拖动调整
    测试完成之后,点击报告查看该次请求的结果
    10

3.2.3.1 Mock入参

Mock 参数每次请求都会生成随机字符串。
11_resize

3.2.3.2 参数变量

YApi 提供了强大的变量参数功能,你可以在测试的时候使用前面接口的 参数返回值 作为 后面接口的参数,即使接口之间存在依赖,也可以轻松 一键测试~

Tips: 参数只能是测试过程中排在前面的接口中的变量参数

格式:$.{key}.{params|body}.{path}

例如:现有两个接口,分别是“导航标题”和“文章列表”
12-1659942132423
文章列表接口需要传参数: 当前标题(id),而这个 id 需要通过 导航标题 的返回值获取,这时应在 文章列表 的参数输入框中根据前者的 key 找到对应 id。
13
其中 $. 是使用 动态变量 的标志,$.269.params 即表示 key 值为 269 用例的请求参数,$.269.body 即表示 key 值为 269 用例的返回值。
14

目前 yapi 中的querybodyheaderpathParam的输入参数已经支持点击选择功能。
无需自己填写表达式,只需在弹窗中选择需要展示的表达式即可。
输入选项包括常量,mock数据,在测试集合中也支持变量选择。
具体用法:单击编辑按钮打开表达式生成器,点击需要的数据创建表达式,这里也可以实时查看表达式结果。
15

3.2.3.3 断言

  1. 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 是否不等于 expected
  • assert.deepEqual(actual, expected):假设: actual = {a:1} 是一个对象,即便 expected = {a:1},如果使用 assert.equal 可能也是不相等的,因为在 js 引用的只是对象的一个指针,需要使用 assert.deepEqual 比较两个对象是否相等
  • assert.notDeepEaual(actual, expected):深度比较两个对象是否不相等
  1. status
    http 状态码

  2. params
    http request params, 合并了 query 和 body

  3. body
    返回 response body

  4. header
    返回 response header

  5. records
    记录的 http 请求信息,假设需要获取 key 为 555 的接口参数或者响应数据,可通过 records[555].params 或 records[555].body 获取

  6. log
    log(message) 函数,调试时使用,log 信息仅仅在断言失败后打印,失败断言前的信息

3.2.4 测试报告

  1. 服务端自动化
    开始测试功能是在浏览器跑自动化测试,他依赖于浏览器的使用环境。服务端自动化测试功能是在YApi服务端跑自动化测试,不需要依赖浏览器环境,只需要访问 YApi 提供的 url 链接就能跑自动化测试,非常的简单易用,而且可以集成到 jenkins。
    16

  2. 运行
    点击服务端测试,用户访问该 url 就可以获取当前测试用例的所有测试结果。

  3. 配置通用规则
    配置通用规则能够使自动化测试,可以基于通用的规则去控制,无需手动一个一个维护case。

测试报告样例如下图所示:
17

3.2.5 Mock Server

定义Mock接口

无需单独定义任何Mock接口,YAPI会默认提供全部已导入接口的Mock数据查询接口。
19

定义Mock返回数据

  1. mockjs
    基于 json + 注释 定义 mock 数据
    18

  2. json-schema(默认方式)
    开启 json-schema 功能后,根据 json-schema 定义的数据结构,生成随机数据。
    21

使用Mock接口

  1. 在代码直接请求 yapi 提供的 mock 地址,不用担心跨域问题。
  2. 使用本地代理

查询mock接口返回示例如下图所示:
20

四、在项目中落地应用

4.1 创建项目

每一个后台服务,创建一个对应的YAPI项目,且工程名称保持一致。
22
23

4.2 项目配置

项目配置中,主要配置两项:
24
项目名称要与工程名称一致。
接口基本路径,使用 /api/项目工程名称

4.3 Swagger自动同步

初始化导入全部接口
25
配置定时任务,按10-30分钟执行一次
合并模式为智能合并
26
定时任务执行后,会有执行记录
27

4.4 请求环境配置

  • 环境域名必须配置
    微服务项目一般配置为网关地址,普通项目直接配置工程地址:

  • 网关权限验证
    支持两种方式,header和cookie。

28
我本地测试,使用cookie中set关键字为ARCTIC_GATEWAY_SESSION,value取值格式为用户名@test,就可以通过网关权限认证。
大家可以根据自己的项目情况自行设置。

4.5 测试集配置

建议配置一定数量的测试集来保障测试效果。

  • 每个测试项目,要创建一个涵盖大部分接口的通用测试集,其中配置如下两条必验规则:
    检查HttpCode是否为200。
    assert.equal(body.success, true)

  • 每个功能模块本身的增删改查,为一个小的测试集。
    除了httpcode为200、success为true以外,还要配置接口之间的断言。比如插入是否成功、修改是否成功、删除是否成功等。

  • 按照业务流程的测试集(可选)
    按照产品设计的业务流程配置测试集,比如正向主业务流程、分支业务流程、逆向业务流程等。

29

4.6 前后端配合

  • 接口定义文档输出里程碑
    前后端一起定义接口与入参
    后端编写接口和相关注解形成Swagger标准文档

  • 前端根据UE原型review接口定义与参数定义
    是否存在错误或缺失的接口。
    是否存在错误或缺失的参数。

  • 联调前,后端编写API单元测试用例并自动化
    全部接口httpcode必须为200,返回值success必须为true。
    每个小功能模块,必须定义增删改查测试集并通过。

五、总结

在团队实际使用过程中,执行力是关键因素,研发经理要保证前后端研发工程师确实认真配置了测试用例,在代码有变化时,测试用例需要一起变化。
这个习惯的养成很重要,初期很不容易,研发经理要进行督促。
在坚持一段时间,团队每个人都在单元测试中获益后,就可以成良好的循环,软件质量一定会上一个台阶。

六、相关资源