利用 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
:使用正则表达式验证字符串格式。minimum
和maximum
:定义数值的最小值和最大值。format
:定义特定的数据格式,如日期、时间等。
演示案例
我们看这个示例,演示如何使用 JSON Schema 验证用户提交的表单数据:
{
"$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"]
}
在上述示例中,我们定义了一个包含 name
、email
和 age
属性的对象,并指定了它们的类型和必需性。
我们来测试一下:
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,应该会校验不通过。执行发现果然报错:
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。
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
方法继续往内部添加数据。
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 字典格式。
from genson import SchemaBuilder
builder = SchemaBuilder()
builder.add_object({'name': 'John', 'age': 25})
schema = builder.to_schema()
print(type(schema)) # 输出: <class 'dict'>
这些是常用的 SchemaBuilder
方法和用法。
有了这个类就方便多了,我们可以通过该类实现一个自动生成jsonschema
校验语法。
实现案例
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
对象 builder
。SchemaBuilder
用于构建 JSON Schema 对象。
接下来,我们使用 add_object
方法将参数 data
添加到 builder
中。这会根据传入的数据生成相应的 JSON Schema。
最后,我们调用 to_schema
方法将 builder
转换为 JSON Schema 对象,并将结果存储在 to_schema
变量中。
最后,我们将生成的 JSON Schema 对象作为函数的返回值返回。
通过调用这个 genson
函数并传入一个字典对象,你将获得该字典数据对应的 JSON Schema。
x = {
"name": "aomaker",
"age": 18,
"email": "111@qq.com"
}
schema = genson(x)
print(schema)
这些这段代码,可以看到我们期望的结果:
{'$schema': 'http://json-schema.org/schema#', 'type': 'object', 'properties': {'name': {'type': 'string'}, 'age': {'type': 'integer'}, 'email': {'type': 'string'}}, 'required': ['age', 'email', 'name']}
pytest
增加断言Schema
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
函数来比较 response
和 schema
是否匹配。如果不匹配,将引发 ValidationError
异常。
测试一下:
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 数据的结构、类型和约束条件,确保数据的有效性和一致性,提高数据交互的质量和可靠性。
转载自:https://juejin.cn/post/7290372531218120745