New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON Schema 的接口测试实战 #27

Open
zhaoqize opened this Issue Jun 1, 2018 · 0 comments

Comments

Projects
None yet
1 participant
@zhaoqize
Owner

zhaoqize commented Jun 1, 2018

“接口返回的数据不对啊!”
我想这句话是前端工程师经常挂在嘴边的
作为前端工程师,与后端工程师对接口是日常工作,每次遇到接口问题,我们都无比头疼。既然这样,那我们能不能通过一种手段来处理这种问题呢?下面的 JSON Schema 就是我的一种尝试。

JSON Schema

JSON Schema is a vocabulary that allows you to annotate and validate JSON documents.

JSON Schema 是用以标注和验证JSON文档的元数据的文档。通俗的说,通过 JSON Schema 我们可以规范和验证 JSON 的格式,符不符合我们的预期。比如某个字段我们通过 JSON Schema 定义为 string,但是返回的 JSON 中该字段是 number ,这种情况通过验证就是不通过。

这里贴一个 JSON Schema 官方的简单例子:

我们来简单分析下这个 Schema 的含义:

  • title 字段:用来描述这个 Schema 是用来做什么的,不具有约束性作用。
  • properties 字段:用来描述这个 Schema 中包含的字段
  • firstName,lastName,age 字段就是我们要描述的 JSON 中要包含的字段
  • type 字段:用来描述字段的类型,这是必须的
  • required 字段:用来描述哪些字段必须的

这时候,对于下面这个 JSON 就是不通过的,因为 Schema 中 age 定义的是 integer

{
   "firstName": "z",
   "lastName": "q",
   "age": "61"
}

check 接口

由于原来项目涉及公司信息,这里使用 demo 进行演示,但是思路是一样的。

jsonschema

其实 JSON Schema 本身描述起来是很复杂的。目前的版本是 draft-07。如果我们的接口是一些简单 JSON 还好,要是很复杂的话,想要写好那还是有些工作量的。所以这里我推荐大家使用 jsonschema,来帮助我们自动生成。然后,我们可以在这个基础上修改。

ajv

既然这里要检验我们的接口是否符合我们的预期,肯定是进行 校验 的。目前校验的库有不少,但是我使用的是 ajv 这个库。用它提供的功能,帮助我们校验,省去不少麻烦。

实战

这里校验 CNODE 的主题,请求接口是 https://cnodejs.org/api/v1/topics?page=1&limit=1

接口格式如下:

{
  "success": true,
  "data": [
    {
      "id": "5ae140407b0e8dc508cca7cc",
      "author_id": "573ab7ba542374db1db0a436",
      "tab": "share",
      "content": "xxx",
      "title": "【NODE PARTY】【上海】【6月9日 13:30】报名&答疑帖",
      "last_reply_at": "2018-06-01T03:01:08.368Z",
      "good": false,
      "top": true,
      "reply_count": 228,
      "visit_count": 8080,
      "create_at": "2018-04-26T02:58:08.067Z",
      "author": {
        "loginname": "aojiaotage",
        "avatar_url": "https://avatars3.githubusercontent.com/u/8339316?v=4&s=120"
      }
   }
  ]
}

通过 jsonschema 生成的 JSON Schema 如下:

{
  "$id": "http://example.com/example.json",
  "type": "object",
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "success": {
      "$id": "/properties/success",
      "type": "boolean",
      "title": "The Success Schema ",
      "default": false,
      "examples": [
        true
      ]
    },
    "data": {
      "$id": "/properties/data",
      "type": "array",
      "items": {
        "$id": "/properties/data/items",
        "type": "object",
        "properties": {
          "id": {
            "$id": "/properties/data/items/properties/id",
            "type": "string",
            "title": "The Id Schema ",
            "default": "",
            "examples": [
              "5ae140407b0e8dc508cca7cc"
            ]
          },
         ....
}

可以看到生成的 JSON Schema 非常的规范,我们可以通过设置,将非必须的字段都去掉。

通过 axios 发送请求,获取返回的报文

const axios = require('axios');
const API = require('../api/index');

/**
 * 描述:获取cnode topic
 */
const getTopic = function () {
  return new Promise((resolve, reject) => {
    axios.get(API.topic)
        .then((response) => {
          resolve(response);
        })
        .catch((error) => {
          reject(error);
        });
  })
}

module.exports = getTopic;

然后对数据进行 JSON Schema 校验

const Ajv = require('ajv');
const ajv = new Ajv(); // options can be passed, e.g. {allErrors: true}
const chalk = require('chalk');

// schema
const topicSchema = require('./schemas/cnode.topic.json');

// json
const getTopic = require('./json/cnode.topic.js');

// check Topic
function checkTopic () {
  getTopic()
    .then((resp) => {
      const validate = ajv.compile(topicSchema);
      const valid = validate(resp.data);
      console.log('---------------------------------------');
      console.log(chalk.green(`请求url: ${resp.request.path}`));
      if (valid) {
        console.log(chalk.green(`校验成功: ${valid}`));
      } else {
        console.log(chalk.red(`校验失败: ${validate.errors}`));
      }
      console.log('---------------------------------------');
    })
    .catch((err) => {
      console.log('---------------------------------------');
      console.log(chalk.red(`请求失败: ${err}`));
      console.log('---------------------------------------');
    })
}

checkTopic();

运行node index.js,返回
image

最后

这个例子很简单,但是到具体的业务中,对于所有(重要)接口的校验,还是需要不少的其他工作。比如

  • 分环境测试
  • 自动生成可配置的 JSON Schema
  • 定时/手动触发校验
  • 校验的上报与统计

其实我觉得这块也应该属于自动化测试的一个环节,目前还在探索和完善中。

JSON Schema 接口测试源码

最后,共勉!💪

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment