在接口自动化测试中使用jsonschema
Whisper Lv4

做接口测试时,传给后端的数据,需要根据API文档做一下数据格式的校验。后端返回给前端的数据也需要根据API文档做数据格式的校验,此时使用JsonSchema来验证数据结构。官方文档

python jsonschema

安装,基本使用参见文档
类型校验,要查看其它的详细文档,注意上方的下拉选择

必填项

使用required来指定必有项

1
2
3
4
5
6
7
8
9
{
"type": "object",
"properties": {
"street_address": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string" }
},
"required": ["street_address", "city", "state"]
}

需要查找某个属性时,记得使用搜索框

enum规定范围

1
2
3
4
{
"type": "string",
"enum": ["NW", "NE", "SW", "SE"]
}

如果指定string为固定值,enum只写一个值

1
2
3
4
{
"type": "string",
"enum": ["NW"]
}

使用组合

anyOf, allOf, oneOf, not组合规则方便我们组合出更严格的校验规则,另外还提供了definitions方式命名一套复杂的校验方案,使用时用$ref引用这个命名的校验方案(数据模式复用)。
allOf:取并集

1
2
3
4
5
6
{
"allOf": [
{ "type": "string" },
{ "maxLength": 5 }
]
}

"short"符合,too long不符合。

oneOf: 满足且只满足一个, 多个满足要报错。
anyOf:满足任意一个 Schema 即可

复用

定义复用snippet

使用definitions,如下,定义了一个需要的复用的address的schema

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"definitions": {
"address": {
"type": "object",
"properties": {
"street_address": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string" }
},
"required": ["street_address", "city", "state"]
}
}
}

使用snippet

使用ref(JSON Pointer),使用刚刚定义的address

1
{ "$ref": "#/definitions/address" }
  1. #指向文档根目录
  2. definitions:找到key未definitions的值
  3. 找到definitions中key未address的值

$ref可以使用相对URI,也可以使用绝对URI,如果要将definitions放在单独的文件中,可以使用相对URI,如{ "$ref": "definitions.json#/address" }

使用python变量复用

json-schema本身的这个很难用,直接使用python中的变量来复用:

a.py

1
a = {"a": "b"}

b.py

1
2
import a
b = {"c": a.a}

python开始验证

1
2
from jsonschema import validate, ValidationError
validate(data, schema)

错误集锦

python使用jsonscheme引用ref报错

1
unknown url type definitions

将definitions放在当前的文档中,没有问题,放在外部文件中,根据官方文档的说明:

main.py文件

1
2
3
4
5
6
7
8
9
10
11
from jsonschema import validate

a = {
"type": "object",
"required": ["shipping_address"],
"properties": {
"shipping_address": {"$ref": "definitions.json#/address"}
}
}
ins = {"billing_address": 1, "shipping_address": 2}
validate(ins, a)

definitions.json文件

1
2
3
4
5
6
7
8
9
10
11
{
"adress": {
"type": "object",
"properties": {
"street_address": {"type": "string"},
"city": {"type": "string"},
"state": {"type": "string"}
},
"required": ["street_address", "city", "state"]
}
}

解决使用file
main.py文件

1
2
3
4
5
6
7
8
9
10
11
from jsonschema import validate

a = {
"type": "object",
"required": ["shipping_address"],
"properties": {
"shipping_address": {"$ref": "file:address.json"}
}
}
ins = {"billing_address": 1, "shipping_address": 2}
validate(ins, a)

这里的file使用的是相对路径,相对当前运行目录。

address.json文件

1
2
3
4
5
6
7
8
9
{
"type": "object",
"properties": {
"street_address": {"type": "string"},
"city": {"type": "string"},
"state": {"type": "string"}
},
"required": ["street_address", "city", "state"]
}

json文件中不能再使用ref,找不到,仍然会报错找不到URL

这里需要一个definition需要写一个单独的文件,暂时没有找到多个definition写到一个json文件中的引用方法。

多层嵌套

丢弃使用xxx.json文件,使用py的dict做为小片段,为了解决多层嵌套。

a.py

1
2
3
address = {"street": "Ls", "sv", "Anni"}
b = {"name": "Ane""address": address}
a = {"a": 1, "b": b}