利用 Pytest 和 Schema 断言测试 JSON 数据格式

前言

笔者测试过程中,接到这样一个测试任务,接口进行重构之后,需要测试同学来验证数据的结构和类型,以防因某个字段被删除或者类型被更改,造成隐藏问题出现的概率增加。那该如何验证数据结构和类型呢?带着这个问题,我们一起探索。

JSON Schema

前言中提到的问题,就需要使用JSON Schema来解决。那到底什么是JSON Schema,又该如何使用呢?

官方文档直达

什么是JSON Schema

JSON Schema 是一种用于验证和描述 JSON 数据结构的语言。它提供了一种标准化的规范方法,可以定义 JSON 数据的结构、数据类型以及相关约束条件。

JSON Schema 的基本语法

JSON Schema 使用 JSON 对象来表示数据结构和约束规则。以下是一些常见的 JSON Schema 关键字:

  • $schema:指定所使用的 JSON Schema 规范版本。
  • type:指定数据的类型,如字符串、数字、布尔值等。
  • properties:定义对象属性及其对应的约束规则。
  • required:指定必需的属性。
  • enum:定义枚举值列表。
  • pattern:使用正则表达式验证字符串格式。
  • minimummaximum:定义数值的最小值和最大值。
  • format:定义特定的数据格式,如日期、时间等。

演示案例

我们看这个示例,演示如何使用 JSON Schema 验证用户提交的表单数据:

bash 复制代码
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string",
    },
    "age": {
      "type": "integer",
      "minimum": 18
    }
  },
  "required": ["name", "email"]
}

在上述示例中,我们定义了一个包含 nameemailage 属性的对象,并指定了它们的类型和必需性。

我们来测试一下:

javascript 复制代码
from jsonschema import validate
​
x = {
    "name": "aomaker",
    "age": 2,
    "email": "111"
}
schema = {
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string",
      "format": "email"
    },
    "age": {
      "type": "integer",
      "minimum": 18
    }
  },
  "required": ["name", "email"]
}
​
validate(x, schema)

这段代码中,x数据中给定age值为2,但是schema中要求age最小值为18,应该会校验不通过。执行发现果然报错:

csharp 复制代码
jsonschema.exceptions.ValidationError: 2 is less than the minimum of 18

我们将age的值设置为大于等于18,即可校验通过。

这样我们将用户提交的数据与以上 JSON Schema 进行验证,我们就可以确保数据的合法性,并及时反馈给用户有关错误或缺失的信息。

你以为到这里就万事大吉了吗?如果响应数据有很多字段,已不是一个个写Schema会变得很困难,有种想放弃的感觉。幸好有genson.

genson

genson 是一个 Python 库,它用于生成符合 JSON Schema 规范的模式(schema)。genson 通过分析现有的 JSON 数据,自动生成相应的 JSON Schema。

安装

使用前,首先需要安装,安装很简单,执行下面这段命令即可:

pip install genson

SchemaBuilder

SchemaBuilder 是 Genson 库中用于构建 JSON Schema 的类。它通过添加对象、属性等元素来构建 JSON Schema 对象,并使用 to_schema 方法将其转换为 JSON 格式。

用法

add_object(obj: Any) -> 'SchemaBuilder'

添加一个包含数据的任意 Python 对象,例如字典、列表或自定义类。这个方法会根据传入的数据生成相应的 JSON Schema。

css 复制代码
from genson import SchemaBuilder
​
builder = SchemaBuilder()
builder.add_object({'name': 'John', 'age': 25})
schema = builder.to_schema()
print(schema)
# 输出: {"type": "object", "properties": 
        {"name": {"type": "string"}, "age": {"type": "integer"}}, 
        "required": ["age", "name"]}

add_property(name: str, value: Any) -> 'SchemaBuilder'

添加一个属性到当前正在构建的对象中。该方法接收两个参数,name 表示属性名,value 表示属性值。添加属性后可以使用 add_object 方法继续往内部添加数据。

go 复制代码
from genson import SchemaBuilder
​
builder = SchemaBuilder()
builder.add_property('name', 'John')
builder.add_property('age', 25)
schema = builder.to_schema()
print(schema)
# 输出: {"type": "object", "properties": 
        {"name": {"type": "string"}, "age": {"type": "integer"}}, 
        "required": ["name", "age"]}

to_schema() -> Dict[str, Any]

将构建好的 JSON Schema 转换为 Python 字典格式。

python 复制代码
from genson import SchemaBuilder
​
builder = SchemaBuilder()
builder.add_object({'name': 'John', 'age': 25})
schema = builder.to_schema()
print(type(schema))  # 输出: <class 'dict'>

这些是常用的 SchemaBuilder 方法和用法。

有了这个类就方便多了,我们可以通过该类实现一个自动生成jsonschema校验语法。

实现案例

python 复制代码
from genson import SchemaBuilder
​
def genson(data: dict = None):
    """
    return schema data
    """
​
    builder = SchemaBuilder()
    builder.add_object(data)
    to_schema = builder.to_schema()
    return to_schema

这段代码,在函数内部,我们创建了一个 SchemaBuilder 对象 builderSchemaBuilder 用于构建 JSON Schema 对象。

接下来,我们使用 add_object 方法将参数 data 添加到 builder 中。这会根据传入的数据生成相应的 JSON Schema。

最后,我们调用 to_schema 方法将 builder 转换为 JSON Schema 对象,并将结果存储在 to_schema 变量中。

最后,我们将生成的 JSON Schema 对象作为函数的返回值返回。

通过调用这个 genson 函数并传入一个字典对象,你将获得该字典数据对应的 JSON Schema。

scss 复制代码
x = {
    "name": "aomaker",
    "age": 18,
    "email": "[email protected]"
}
schema = genson(x)
​
print(schema)

这些这段代码,可以看到我们期望的结果:

dart 复制代码
{'$schema': 'http://json-schema.org/schema#', 'type': 'object', 'properties': {'name': {'type': 'string'}, 'age': {'type': 'integer'}, 'email': {'type': 'string'}}, 'required': ['age', 'email', 'name']}
​

pytest增加断言Schema

python 复制代码
def assert_schema(schema, response):
    """
    Assert JSON Schema
    """
    try:
        validate(instance=response, schema=schema)
    except ValidationError as msg:
        raise AssertionError

代码定义了一个名为 assert_schema 的函数,用于验证 JSON 数据是否符合给定的 JSON Schema。

这个函数接受两个参数:

  • schema:表示要验证的 JSON Schema,通常是一个字典或从 JSON 文件加载的对象。
  • response:表示要验证的 JSON 数据,通常是从 API 响应中获取的数据。

函数的主要逻辑是使用 validate 函数来比较 responseschema 是否匹配。如果不匹配,将引发 ValidationError 异常。

测试一下:

makefile 复制代码
schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer"}
    },
    "required": ["name", "age"]
}
​
response = {
    "name": "John Doe",
    "age": 25
}
​
# 调用 assert_schema 函数进行验证
assert_schema(schema, response)
​

如果 API 响应数据不符合 JSON Schema,assert_schema 函数将引发断言错误,并显示详细的验证错误消息。

最后

genson虽然可以帮助我们快速生成Scheam,但预期结果还是要手动进行维护的。当然,后续我们其实可以在做接口自动化时,在接口被调用的时候自动存储到数据库,然后持续维护这个表的数据即可,后续想办法实现一下。JSON Schema已经可以解决我们前言中提到的问题了。JSON Schema 可以帮助我们定义和验证 JSON 数据的结构、类型和约束条件,确保数据的有效性和一致性,提高数据交互的质量和可靠性。

相关推荐
鹏码纵横4 小时前
已解决:java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 异常的正确解决方法,亲测有效!!!
java·python·mysql
仙人掌_lz4 小时前
Qwen-3 微调实战:用 Python 和 Unsloth 打造专属 AI 模型
人工智能·python·ai·lora·llm·微调·qwen3
weixin_985432114 小时前
Spring Boot 中的 @ConditionalOnBean 注解详解
java·spring boot·后端
猎人everest4 小时前
快速搭建运行Django第一个应用—投票
后端·python·django
猎人everest4 小时前
Django的HelloWorld程序
开发语言·python·django
chusheng18405 小时前
2025最新版!Windows Python3 超详细安装图文教程(支持 Python3 全版本)
windows·python·python3下载·python 安装教程·python3 安装教程
别勉.5 小时前
Python Day50
开发语言·python
xiaohanbao096 小时前
day54 python对抗生成网络
网络·python·深度学习·学习
爬虫程序猿6 小时前
利用 Python 爬虫按关键字搜索 1688 商品
开发语言·爬虫·python
英杰.王6 小时前
深入 Java 泛型:基础应用与实战技巧
java·windows·python