通过 JSON Schema 完成接口自动化测试的数据验证

什么是 JSON Schema

JSON Schema,也称为 JSON 模式,下面一段话来自百度百科的介绍:
JSON Schema 是描述你的 JSON 数据格式;JSON 模式(应用程序/模式 + JSON)有多种用途,其中之一就是实例验证。验证过程可以是交互式或非交互式的。例如,应用程序可以使用 JSON 模式来构建用户界面使互动的内容生成除了用户输入检查或验证各种来源获取的数据。
一般使用 JSON Schema 来进行 JSON 数据格式验证,在数据提交到业务层次之前进行 JSON 格式的验证。
jsonschema 百度百科

JSON Schema 官网的描述摘要:http://json-schema.org/

  1. JSON Schema 是基于 JSON 格式定义 JSON 数据结构的规范
  2. 用于描述现有的数据格式(JSON 数据)
  3. 清晰的人机可读文档:定义的 JSON Schema 具有人类和机器都可读的特性
  4. 使用 JSON Schema 可完成完整的 JSON 结构和数据验证
  5. 可用于自动化测试和确保客户提交的数据质量(如下我们只讨论在自动化测试中的应用)

下面是一段 JSON 示例:
文档中包含如下信息:

{
  "teacherId": 1,
  "teacherName": "Happy",
  "age": 18,
  "tags": [ "JAVA", "Python","Automation" ]
}

例子很简单,但是中间有些问题有待解决,这也是我们在自动化测试中可能会关注的信息,比如以下这些:

如果在自动化测试中需要来验证上述问题,方法一可以通过提取数据的方式完成,参考之前我写过的文章:
使用 JsonPath 完成接口自动化测试中参数关联和数据验证
使用 JsonPath 更适合关键信息的提取和验证,JSON Schema 更适合回答上面的这些问题。

开始写 JSON Schema

首先我们从如下一些关键字开始:

针对上述 JSON 案例初步编写的 JSON Schema 如下

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/teacher.schema.json",
  "title": "老师信息",
  "description": "柠檬班的一个老师信息",
  "type": "object"
}

定义属性

teacherId 属性

根据约束我们在上面 JSON Schema 更新如下:

最后的 JSON Schema 如下:

{
   "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/teacher.schema.json",
  "title": "老师信息",
  "description": "柠檬班的一个老师信息",
  "type": "object",
  "properties": {
    "teacherId": {
      "description": "老师信息的唯一标识符",
      "type": "integer"
    }
  },
  "required": [ "teacherId" ]
}

teacherName 属性

添加对 teacherName 属性的约束后,JSON Schema 如下,其中:

{
   "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/teacher.schema.json",
  "title": "老师信息",
  "description": "柠檬班的一个老师信息",
  "type": "object",
  "properties": {
    "teacherId": {
      "description": "老师信息的唯一标识符",
      "type": "integer"
    },
    "teacherName": {
      "description": "老师的名称",
      "type": "string"
    }
  },
  "required": [ "teacherId","teacherName" ]
}

age 属性

{
   "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/teacher.schema.json",
  "title": "老师信息",
  "description": "柠檬班的一个老师信息",
  "type": "object",
  "properties": {
    "teacherId": {
      "description": "老师信息的唯一标识符",
      "type": "integer"
    },
    "teacherName": {
      "description": "老师的名称",
      "type": "string"
    },
    "age": {
      "description": "老师的年龄",
      "type": "number",
      "minimum": 18
    }
  },
  "required": [ "teacherId","teacherName","age" ]
}

tags 属性

tags 属性要求如下:

JSON Schema 需要做如下修改:

升级后 JSON Schema 如下

{
   "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/teacher.schema.json",
  "title": "老师信息",
  "description": "柠檬班的一个老师信息",
  "type": "object",
  "properties": {
    "teacherId": {
      "description": "老师信息的唯一标识符",
      "type": "integer"
    },
    "teacherName": {
      "description": "老师的名称",
      "type": "string"
    },
    "age": {
      "description": "老师的年龄",
      "type": "number",
      "minimum": 18
    },
    "tags": {
      "description": "老师的标签",
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "uniqueItems": true
    }
  },
  "required": [ "teacherId","teacherName","age" ]
}

Java 中的 JSON Schema 的校验

通过 maven 引入相关的 jar 包

<dependency>
    <groupId>com.github.java-json-tools</groupId>
    <artifactId>json-schema-validator</artifactId>
    <version>2.2.10</version>
</dependency>

编写程序校验

//要校验的json字符串(如来自自动化测试中的响应结果)
String jsonStr = "{\r\n" + "  \"teacherId\": 1,\r\n" + "  \"teacherName\": \"Happy\",\r\n" + "  \"age\": 18,\r\n"
		+ "  \"tags\": [ \"JAVA\", \"Python\",\"Automation\" ]\r\n" + "}";
//根据响应结果需求,编写的JSON Schema
String jsonSchema = "{\r\n" + "   \"$schema\": \"http://json-schema.org/draft-07/schema#\",\r\n"
		+ "  \"$id\": \"http://example.com/teacher.schema.json\",\r\n" + "  \"title\": \"老师信息\",\r\n"
		+ "  \"description\": \"柠檬班的一个老师信息\",\r\n" + "  \"type\": \"object\",\r\n" + "  \"properties\": {\r\n"
		+ "    \"teacherId\": {\r\n" + "      \"description\": \"老师信息的唯一标识符\",\r\n"
		+ "      \"type\": \"integer\"\r\n" + "    },\r\n" + "    \"teacherName\": {\r\n"
		+ "      \"description\": \"老师的名称\",\r\n" + "      \"type\": \"string\"\r\n" + "    },\r\n"
		+ "    \"age\": {\r\n" + "      \"description\": \"老师的年龄\",\r\n" + "      \"type\": \"number\",\r\n"
		+ "      \"minimum\": 18\r\n" + "    },\r\n" + "    \"tags\": {\r\n"
		+ "      \"description\": \"老师的标签\",\r\n" + "      \"type\": \"array\",\r\n" + "      \"items\": {\r\n"
		+ "        \"type\": \"string\"\r\n" + "      },\r\n" + "      \"minItems\": 1,\r\n"
		+ "      \"uniqueItems\": true\r\n" + "    }\r\n" + "  },\r\n"
		+ "  \"required\": [ \"teacherId\",\"teacherName\",\"age\" ]\r\n" + "}";

//创建JsonSchema工厂
JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
//通过jsonSchema获得对应JsonNode对象
JsonNode schemaNode = JsonLoader.fromString(jsonSchema);
//通过jsonStr字符串获得对应JsonNode对象
JsonNode dataNode = JsonLoader.fromString(jsonStr);
//通过jsonSchema的JsonNode对象获得JsonSchema对象
JsonSchema schema = factory.getJsonSchema(schemaNode);
//使用json-schema-validator中JsonSchema对象的validate方法对数据进行校验
//获得处理的报告信息
ProcessingReport processingReport = schema.validate(dataNode);
//获取完整报告信息
System.out.println(processingReport);
//判断校验是否成功,如果为true表示成功,否则失败
System.out.println(processingReport.isSuccess());

输出结果如下

com.github.fge.jsonschema.core.report.ListProcessingReport: success
--- BEGIN MESSAGES ---
warning: the following keywords are unknown and will be ignored: [$id]
    level: "warning"
    schema: {"loadingURI":"#","pointer":""}
    domain: "syntax"
    ignored: ["$id"]
---  END MESSAGES  ---

true

最后校验的结果为 true,表述校验通过,说明我们的 JSON 数据不管从结果还是数据上都是符合要求的,
如果我们把老师的信息调整如下:

{
  "teacherId": 1,
  "teacherName": "Happy",
  "age": 15,
  "tags": [ "JAVA", "JAVA","Automation" ]
}

校验结果为:

com.github.fge.jsonschema.core.report.ListProcessingReport: failure
--- BEGIN MESSAGES ---
warning: the following keywords are unknown and will be ignored: [$id]
    level: "warning"
    schema: {"loadingURI":"#","pointer":""}
    domain: "syntax"
    ignored: ["$id"]
error: numeric instance is lower than the required minimum (minimum: 18, found: 15)
    level: "error"
    schema: {"loadingURI":"#","pointer":"/properties/age"}
    instance: {"pointer":"/age"}
    domain: "validation"
    keyword: "minimum"
    minimum: 18
    found: 15
error: array must not contain duplicate elements
    level: "error"
    schema: {"loadingURI":"#","pointer":"/properties/tags"}
    instance: {"pointer":"/tags"}
    domain: "validation"
    keyword: "uniqueItems"
---  END MESSAGES  ---

false

校验结果 false,表述失败,处理报告中对校验不通过的地方也有原因描述

至此,大家可以在自己的自动化测试框架应用上 JSON Schema,对响应结果为 JSON 格式的数据进行完整的结构和数据校验

更多关于 JSON Schema 的知识可参考:

2 操作
happy 在 2020-09-14 17:37:54 更新了该帖
happy 在 2020-07-30 09:13:50 更新了该帖
3 回帖
请输入回帖内容 ...
  • briller

    Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.base.Platform.precomputeCharMatcher(Lcom/google/common/base/CharMatcher;)Lcom/google/common/base/CharMatcher;

    抛出这个错误,有遇到过么?一摸一样的代码

    image.png

  • happy

    添加如下依赖试试

    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>19.0</version>
    </dependency>
    
  • Lutra

    image.png
    image.png
    image.png
    您好,想问一下,JSON 文件修改后,对于必须校验的字段,不进行校验了,是有什么地方错误吗