一站式接口文档及测试工具yapi介绍

proginn468312

共 5699字,需浏览 12分钟

 · 2020-08-25

我们部门正在使用yapi做接口文档的管理,较之之前纯手工写接口注释的方式确实方便了不少。

功能介绍

稍微看了一下,发现yapi除了做接口文档的可视化管理之外,还有不少的功能。

按照官方说法,YApi 是一个可本地部署的、打通前后端及QA的、可视化的接口管理平台。

YApi 是高效、易用、功能强大的 api 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理。

  • 基于 Json5 和 Mockjs 定义接口返回数据的结构和文档,效率提升多倍
  • 扁平化权限设计,即保证了大型企业级项目的管理,又保证了易用性
  • 类似 postman 的接口调试
  • 自动化测试, 支持对 Response 断言
  • MockServer 除支持普通的随机 mock 外,还增加了 Mock 期望功能,根据设置的请求过滤规则,返回期望数据
  • 支持 postman, har, swagger 数据导入
  • 免费开源,内网部署,信息再也不怕泄露了

亮点是支持类似于postman的接口调试方式,这对测试同学会比较友好;另外还支持自动化测试,支持response的断言。

自动化测试

那么yapi如何做自动化测试的呢?

yapi定义了包含测试集、Pre-Script 、Test-Script 三方面。

  • 测试集: 在平时的开发过程中,经常遇到的一个问题是每次调试接口都需要重新填写参数,YApi测试集能够保存之前填写的参数,方便下次的调试。每个的请求参数还可以通过前面已请求的接口数据读取,或填写mock随机字符串,通过设置断言脚本验证返回数据的正确性。

  • Pre-Script:Pre-Script 包括请求参数处理脚本和响应数据处理脚本两部分。通过自定义 js 脚本方式改变请求的参数和返回的 response 数据。他的使用场景如下:(1)接口请求参数需要加密及返回 response 解密;(2)接口请求参数需要添加计算 token

  • Test-Script (测试脚本): 通过自定义脚本断言接口参数或返回 response 数据,在接口用例页面点击 Test 编辑。

具体示例:


assert.equal(body.errcode, 0)assert.equal(body.data.group_name, 'testGroup')assert.equal(status, 200)

总的来看跟postman支持的测试能力差不多。

插件

yapi支持如下的一些插件

  • yapi sso 登录插件
  • yapi cas 登录插件 By wsfe
  • yapi gitlab集成插件
  • oauth2.0登录
  • rap平台数据导入
  • dingding 钉钉机器人推送插件
  • export-docx-data 数据导出docx文档
  • interface-oauth-token 定时自动获取鉴权token的插件
  • import-swagger-customize 导入指定swagger接口

其中oauth和swagger插件是相当实用的。

安装和部署

yapi的后端是用nodejs实现的,所以安装方式无非就是先装nodejs,再npm install,最后加个pm2做服务管理。

使用我们提供的 yapi-cli 工具,部署 YApi 平台是非常容易的。执行 yapi server 启动可视化部署程序,输入相应的配置和点击开始部署,就能完成整个网站的部署。部署完成之后,可按照提示信息,执行 node/{网站路径/server/app.js} 启动服务器。在浏览器打开指定url, 点击登录输入您刚才设置的管理员邮箱,默认密码为 ymfe.org 登录系统(默认密码可在个人中心修改)。

npm install -g yapi-cli --registry https://registry.npm.taobao.org
yapi server

利用pm2方便服务管理维护。

npm install pm2 -g  //安装pm2
cd {项目目录}
pm2 start "vendors/server/app.js" --name yapi //pm2管理yapi服务
pm2 info yapi //查看服务信息
pm2 stop yapi //停止服务
pm2 restart yapi //重启服务

代码实现

随便看了一眼yapi的代码,对于这种前后端分离的项目,我建议大家可以先看后端的具体实体实现,也就是model层。

第一个实体是interface,看名字盲猜代表的是接口的意思。

getSchema() {   return {     title: { type: String, required: true },     uid: { type: Number, required: true },     path: { type: String, required: true },     method: { type: String, required: true },     project_id: { type: Number, required: true },     catid: { type: Number, required: true },     edit_uid: { type: Number, default: 0 },     status: { type: String, enum: ['undone', 'done'], default: 'undone' },     desc: String,     markdown: String,     add_time: Number,     up_time: Number,     type: { type: String, enum: ['static', 'var'], default: 'static' },     query_path: {       path: String,       params: [         {           name: String,           value: String         }       ]     },     req_query: [       {         name: String,         value: String,         example: String,         desc: String,         required: {           type: String,           enum: ['1', '0'],           default: '1'         }       }     ],     req_headers: [       {         name: String,         value: String,         example: String,         desc: String,         required: {           type: String,           enum: ['1', '0'],           default: '1'         }       }     ],     req_params: [       {         name: String,         desc: String,         example: String       }     ],     req_body_type: {       type: String,       enum: ['form', 'json', 'text', 'file', 'raw']     },     req_body_is_json_schema: { type: Boolean, default: false },     req_body_form: [       {         name: String,         type: { type: String, enum: ['text', 'file'] },         example: String,         value: String,         desc: String,         required: {           type: String,           enum: ['1', '0'],           default: '1'         }       }     ],     req_body_other: String,     res_body_type: {       type: String,       enum: ['json', 'text', 'xml', 'raw', 'json-schema']     },     res_body: String,     res_body_is_json_schema: { type: Boolean, default: false },     custom_field_value: String,     field2: String,     field3: String,     api_opened: { type: Boolean, default: false },     index: { type: Number, default: 0 },     tag: Array   }; }

看了一下schema,果然不出所料,基本上一个接口的方方面面都定义到了。

再看interfaceCase.js,继续盲猜这个类用来表示接口测试用例。

getSchema() {   return {     casename: { type: String, required: true },     uid: { type: Number, required: true },     col_id: { type: Number, required: true },     index: { type: Number, default: 0 },     project_id: { type: Number, required: true },     interface_id: { type: Number, required: true },     add_time: Number,     up_time: Number,     case_env: { type: String },     req_params: [       {         name: String,         value: String       }     ],     req_headers: [       {         name: String,         value: String       }     ],     req_query: [       {         name: String,         value: String,         enable: { type: Boolean, default: true }       }     ],
req_body_form: [ { name: String, value: String, enable: { type: Boolean, default: true } } ], req_body_other: String, test_res_body: String, test_status: { type: String, enum: ['ok', 'invalid', 'error', ''] }, test_res_header: Schema.Types.Mixed, mock_verify: { type: Boolean, default: false }, enable_script: { type: Boolean, default: false }, test_script: String }; }

梅开二度,这里有个字段是test_script,没仔细追代码了,不过估计测试的断言都以代码的形式存在里面。

根据思路,大家可以把model文件全部读一遍,这样就应该可以大致了解yapi的持久化层实现了。

功能实现层大家可以去读controller里的代码,ui层可以读client里的代码。

思考

总而言之,yapi基本上就是我们很多测试开发同学所开发的接口测试平台,支持接口文档查看,简单的接口自动化和mock等。

有志于从事测试开发的同学可以精读一下代码,相信会有不少收获。

需要搭建内部接口测试平台的同学可以直接私有化部署,用docker compose的话安装体验更佳。

(本文来自测试圈TC,作者乙醇)

- End -


浏览 11
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报