7.YAML和JSON Schema

文章目录

  • 2.接口自动化测试
    • [2.6 YAML](#2.6 YAML)
      • [2.6.1 YAML介绍](#2.6.1 YAML介绍)
      • [2.6.2 YAML使用](#2.6.2 YAML使用)
    • [2.7 JSON Schema](#2.7 JSON Schema)
      • [2.7.1 安装](#2.7.1 安装)
      • [2.7.2 介绍](#2.7.2 介绍)
        • [2.7.2.1 数据类型](#2.7.2.1 数据类型)
          • [代码1:string, boolean 类型](#代码1:string, boolean 类型)
          • [代码2:array, object, number 类型](#代码2:array, object, number 类型)
          • [代码3:null 类型](#代码3:null 类型)
        • [2.7.2.2 最大最小值](#2.7.2.2 最大最小值)
          • [代码1:minimum / maximum (包含边界)](#代码1:minimum / maximum (包含边界))
          • [代码2:exclusiveMinimum / exclusiveMaximum (不包含边界)](#代码2:exclusiveMinimum / exclusiveMaximum (不包含边界))
        • [2.7.2.3 字符串特殊校验](#2.7.2.3 字符串特殊校验)
        • [2.7.2.4 数组约束](#2.7.2.4 数组约束)
        • [2.7.2.5 对象约束](#2.7.2.5 对象约束)
        • [2.7.2.6 必需属性](#2.7.2.6 必需属性)
        • [2.7.2.7 依赖关系](#2.7.2.7 依赖关系)

2.接口自动化测试

2.6 YAML

官方文档:https://pyyaml.org/wiki/PyYAMLDocumentation
YAML是一种数据序列化语言,用于以人类可读的形式存储信息。它最初代表"Yet Another Markup Language",但后来更改为" YAML Ain't Markup Language"(YAML不是一种标记语言),以区别于真正的标记语言。它类似于XMLJSON文件,但使用更简洁的语法。
特点:

  • YAML 是一种非常简单的基于文本的人类可读的语言,用于在人和计算机之间交换数据。

  • YAML 是不是一种编程语言。它主要用于存储配置信息。

  • YAML 的缩进就像 Python 的缩进一样优雅。

  • YAML 还减少了 JSONXML 文件中的大部分"噪音"格式,例如引号、方括号和大括号。
    注意:

  • YAML 是区分大小写。

  • YAML 不允许使用制表符 Tab 键,(之所以按下 Tab YAML 仍能使用,是因为编辑器被配置为按下 Tab 键会导致插入适当数量的空格)。

  • YAML 是遵循严格缩进的。


2.6.1 YAML介绍

YAML 文件的后缀名是 .yaml.yml ,本着能少写不多写的原则,我们常用的是 .yml

yaml 中支持不同数据类型,但在写法上稍有区别,详见下表:

YAML JSON
简单标量值
整数和浮点数
布尔值
字符串
列表
映射(字典)
嵌套结构

以上语法若短时间内无法掌握,我们也有很多工具可供使用,如jsonyaml

https://www.jashtool.com/json/to-yaml


2.6.2 YAML使用

yaml 文件通常作为配置文件来使用,可以使用 yaml 库来读取和写入 YAML 文件

安装yaml

python 复制代码
pip install PyYAML==6.0.1

创建yaml文件

读取和写入yaml文件:

我们随便创建一个.py文件:

python 复制代码
import yaml

#追加写入
def write_yaml(filename, data):
  with open(filename, encoding="utf-8", mode="a+") as f:
    yaml.safe_dump(data, stream=f)
#读取
def read_yaml(filename, key):
  with open(filename, encoding="utf-8", mode="r") as f:
    data = yaml.safe_load(f)
    return data[key]
#清空
def clear_yaml(filename):
  with open(filename, encoding="utf-8", mode="w") as f:
    f.truncate()
def test_yml():
  #写入yaml文件
  data = {"str":"12345"}
  write_yaml('test.yml',data)
  #读取yaml文件
  ret = read_yaml('test.yml',"str")
  print("ret:", ret)
  #清空yaml文件
  clear_yaml('test.yml')

打印:


2.7 JSON Schema

JSON Schema一个用来定义和校验JSONweb规范,简而言之,JSON Schema是用来校验json是否符合预期。

根据 json 创建 JSON Schema 后,你可以使用你选择的语言中的验证器将示例数据与你的模式进行验证。


2.7.1 安装

python 复制代码
pip install jsonschema==4.23.0

2.7.2 介绍

Json

json 复制代码
{
  "code": "SUCCESS",
  "errMsg": "",
  "data": false
}

JSON Schema

json 复制代码
{
  "type": "object",
  "required": [],
  "properties": {
    "code": {
      "type": "string"
    },
    "errMsg": {
      "type": "string"
    },
    "data": {
      "type": "string"
    }
  }
}

通过上面的对比可见, JSON Schema 从多个方面对 JSON 数据进行校验。如" type "、" required "、" properties "等以确保其正确性和一致性。接下来我们来了解 JSON Schema 中的关键词以及作用。

jsonJSON Schema太麻烦?使用现有工具自动转换:https://tooltt.com/json2schema/

注意:工具不是万能的,结果可能存在错误,要对自动生成的结果进行二次检查

示例:校验博客列表页返回的json数据

python 复制代码
import requests
from jsonschema.validators import validate

def test_json():
    schema = {
        "type": "object",
        "required": [],
        "properties": {
            "code": {
                "type": "string"
            },
            "errMsg": {
                "type": "string"
            },
            "data": {
                "type": "array",
                "items": {
                    "type": "object",
                    "required": [],
                    "properties": {
                        "id": {
                            "type": "number"
                        },
                        "title": {
                            "type": "string"
                        },
                        "content": {
                            "type": "string"
                        },
                        "userId": {
                            "type": "number"
                        },
                        "deleteFlag": {
                            "type": "number"
                        },
                        "createTime": {
                            "type": "string"
                        },
                        "updateTime": {
                            "type": "string"
                        },
                        "loginUser": {
                            "type": "boolean"
                        }
                    }
                }
            }
        }
    }

    # 接口URL:博客系统的获取博客列表接口
    url = "http://47.108.157.13:8090/blog/getList"
    # 请求头配置,包含用户认证token
    header = {
        # 用户token,用于身份验证和授权
        "user_token_header": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MywidXNlck5hbWUiOiJ6aGFuZ3NhbiIsImV4cCI6MTc2NjI5Mzk2OX0.B1IUyfh-YJGX9GMQ5dHcIl1Cygy9ttKCOS15Wz3jRVs"
    }
    r = requests.get(url=url, headers=header)
    validate(r.json(), schema)

"user_token_header"的值可以从下面找到:

这里只做演示,可能我的代码在你那边就跑不通了,因为对应的token可能会被更新,不过知道怎么用就行了。


2.7.2.1 数据类型

type 关键字指定了数据类型。

可以验证 JSON 数据中每个属性的数据类型是否符合预期。常用的数据类型包括:

type 解释
string 字符串类型,用于文本数据。
number 数字类型,用于表示浮点数。
integer 整数类型,用于表示整数。
boolean 布尔类型,值为 truefalse
object 对象类型,用于嵌套的 JSON 对象。
array 数组类型,用于列表或集合。
null 空值类型。

示例:

json 复制代码
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "type": "integer"
    }
  }
}

properties 是一个验证关键字。当你定义 properties 时,你创建了一个对象,其中每个属性代表正在验证的 JSON 数据中的一个键。


代码1:string, boolean 类型
python 复制代码
import pytest
from jsonschema import validate

def test_basic_types_string_boolean():
    """测试 string 和 boolean 基础类型"""
    # 定义待验证的 JSON 数据
    # 这是一个典型的接口返回数据结构,包含状态码、错误信息和数据
    json_data = {
        "code": "SUCCESS",  # 状态码,字符串类型
        "errMsg": "",  # 错误信息,字符串类型(空表示无错误)
        "data": False  # 实际数据,布尔类型
    }

    # 定义 JSON Schema,用于规定数据结构和类型
    json_schema = {
        "type": "object",  # 根节点类型为对象
        "properties": {  # 定义对象的属性
            "code": {
                "type": "string"  # code 字段必须是字符串类型
            },
            "errMsg": {
                "type": "string"  # errMsg 字段必须是字符串类型
            },
            "data": {
                "type": "boolean"  # data 字段必须是布尔类型
            }
        }
    }

    # 使用 validate 函数验证 json_data 是否符合 json_schema 的定义
    # 如果 json_data 不符合 schema,这里会抛出 jsonschema.exceptions.ValidationError 异常
    validate(instance=json_data, schema=json_schema)

    # 验证通过后打印成功信息
    print("✅ test_basic_types_string_boolean: 验证通过")

打印:


代码2:array, object, number 类型
python 复制代码
import requests
from jsonschema import validate

def test_complex_types_array_object_number():
    """测试 array, object, number 嵌套类型"""
    url = "http://47.108.157.13:8090/blog/getList"
    header = {
        "user_token_header": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MywidXNlck5hbWUiOiJ6aGFuZ3NhbiIsImV4cCI6MTc2NjI5Mzk2OX0.B1IUyfh-YJGX9GMQ5dHcIl1Cygy9ttKCOS15Wz3jRVs"
    }
    r = requests.get(url=url, headers=header)
    json_data = r.json()

    json_schema = {
        "type": "object",
        "properties": {
            "data": {
                "type": "array",
                "items": {  # 定义数组中每个元素的结构
                    "type": "object",
                    "properties": {
                        "id": {"type": "number"},
                        "title": {"type": "string"},
                        "content": {"type": "string"},
                        "userId": {"type": "number"},
                        "deleteFlag": {"type": "number"},
                        "createTime": {"type": "string"},
                        "updateTime": {"type": "string"},
                        "loginUser": {"type": "boolean"}
                    }
                }
            }
        }
    }
    validate(instance=json_data, schema=json_schema)
    print("✅ test_complex_types_array_object_number: 验证通过")

打印:


代码3:null 类型
python 复制代码
import requests
from jsonschema import validate

def test_basic_type_null():
    """测试 null 类型"""
    json_data = {
        "data": [{"name": "zhangsan", "age": 20}],
        "addr": None
    }

    json_schema = {
        "type": "object",
        "properties": {
            "addr": {
                "type": "null"
            },
            "data": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                        "age": {"type": "number"}
                    }
                }
            }
        }
    }

    validate(instance=json_data, schema=json_schema)
    print("✅ test_basic_type_null: 验证通过")

打印:


2.7.2.2 最大最小值
  • minimummaximum :指定数值的最小值和最大值。
  • exclusiveMinimumexclusiveMaximum :指定数值必须严格大于或小于某个值(不包含等于)。

示例:

json 复制代码
{
  "type": "object",
  "properties": {
    "age": {
      "type": "integer",
      "minimum": 0,
      "maximum": 120
    }
  }
}

代码1:minimum / maximum (包含边界)

这个例子验证 age 的值必须在 0 到 100 之间(包含 0 和 100)。

python 复制代码
import requests
from jsonschema import validate

def test_numeric_range_inclusive():
    """测试数值范围 (包含边界)"""
    json_data = {"name": "zhangsan", "age": 100} # age = 0 或 100 都会通过
    json_schema = {
        "type": "object",
        "properties": {
            "name": {"type": "string"},
            "age": {
                "type": "number",
                "minimum": 0,
                "maximum": 100
            }
        }
    }
    validate(instance=json_data, schema=json_schema)
    print("✅ test_numeric_range_inclusive: 验证通过")

打印:


代码2:exclusiveMinimum / exclusiveMaximum (不包含边界)

这个例子验证 age 的值必须严格大于 0 且严格小于 100。

python 复制代码
import requests
from jsonschema import validate

def test_numeric_range_exclusive():
    """测试数值范围 (不包含边界)"""
    json_data = {"name": "zhangsan", "age": 99.9} # age = 0 或 100 会失败
    json_schema = {
        "type": "object",
        "properties": {
            "name": {"type": "string"},
            "age": {
                "type": "number",
                "exclusiveMinimum": 0,
                "exclusiveMaximum": 100
            }
        }
    }
    validate(instance=json_data, schema=json_schema)
    print("✅ test_numeric_range_exclusive: 验证通过")

打印:


2.7.2.3 字符串特殊校验
  • pattern :使用正则表达式来验证字符串是否符合特定的模式。

示例:

json 复制代码
{
  "type": "object",
  "properties": {
    "email": {
      "type": "string"
    },
    "username": {
      "type": "string",
      "pattern": "/S+"
    }
  }
}

代码:

python 复制代码
import requests
from jsonschema import validate

def test_string_pattern():
    """测试字符串正则表达式校验"""
    # 注意:原始JSON中是 "\S{20,}",在Python字符串中需要写成 "\\S{20,}" 或 r"\S{20,}"
    json_data = {"name": "zhangsan_with_a_very_long_name", "age": 10}
    json_schema = {
        "type": "object",
        "properties": {
            "name": {
                "type": "string",
                "pattern": "\\S{20,}"  # \S 表示非空白字符, {20,} 表示至少20个
            },
            "age": {"type": "number"}
        }
    }
    validate(instance=json_data, schema=json_schema)
    print("✅ test_string_pattern: 验证通过")

打印:


2.7.2.4 数组约束
  • minItemsmaxItems :指定数组的最小和最大长度。
  • uniqueItems :确保数组中的元素是唯一的。
  • items :定义数组中每个元素的类型和约束。

示例:

json 复制代码
{
    "type": "object",
    "properties": {
        "tags": {
            "type": "array",
            "items": {
                "type": "string"
            },
            "minItems": 1,
            "uniqueItems": True
        }
    }
}

代码:

python 复制代码
import requests
from jsonschema import validate

def test_array_constraints():
    """测试数组长度和唯一性约束"""
    json_data = {"data": ["hello", "world", "hello"], "str": "hello"} # str类型故意写错,在另一个模块修正
    json_schema = {
        "type": "object",
        "properties": {
            "data": {
                "type": "array",
                "minItems": 1,
                "maxItems": 5,
                "uniqueItems": False,  # 允许重复元素
                "items": {"type": "string"}
            },
            "str": {"type": "string"} # 修正为 string 以便本模块通过
        }
    }
    validate(instance=json_data, schema=json_schema)
    print("✅ test_array_constraints: 验证通过")

打印:


2.7.2.5 对象约束
  • minPropertiesmaxProperties :指定对象的最小和最大属性数量。
  • additionalProperties :控制是否允许对象中存在未在 properties 中定义的额外属性,默认为True

示例:

json 复制代码
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    }
  },
  "minProperties": 1,
  "additionalProperties": False
}

代码:

python 复制代码
import requests
from jsonschema import validate

def test_object_additional_properties():
    """测试对象不允许额外属性"""
    json_data = {
        "username": "zhagnsan",
        "hobby": {}  # hobby 对象是空的,没有额外属性
    }
    schema = {
        "type": "object",
        "properties": {
            "username": {"type": "string"},
            "hobby": {
                "type": "object",
                "properties": {
                    "aaa": {"type": "string"},
                    "bbb": {"type": "string"}
                },
                "additionalProperties": False  # hobby 对象内不允许有 aaa, bbb 之外的属性
            }
        }
    }
    validate(instance=json_data, schema=schema)
    print("✅ test_object_additional_properties: 验证通过")

# 如果 json_data 是 {"username": "zhangsan", "hobby": {"aaa": "a", "ccc": "c"}},验证会失败

打印:


2.7.2.6 必需属性
  • 通过 required 关键字,JSON Schema 可以指定哪些属性是必需的。如果 JSON 实例中缺少这些必需属性,验证将失败。

示例:

json 复制代码
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string"
    }
  },
  "required": [
    "name",
    "email"
  ]
}

代码:

python 复制代码
import requests
from jsonschema import validate

def test_required_properties():
    """测试必需属性"""
    json_data = {
        "code": "SUCCESS",
        "errMsg": "",
        "data": [
            {
                "id": 21430,
                "title": "自动化测试实例",
                "loginUser": False
            }
        ]
    }
    json_schema = {
        "type": "object",
        "required": ["code", "errMsg", "data"],  # 顶层对象必需属性
        "properties": {
            "code": {"type": "string"},
            "errMsg": {"type": "string"},
            "data": {
                "type": "array",
                "items": {
                    "type": "object",
                    "required": ["id", "loginUser"],  # 数组内每个对象的必需属性
                    "properties": {
                        "id": {"type": "number"},
                        "title": {"type": "string"},
                        "loginUser": {"type": "boolean"}
                    }
                }
            }
        }
    }
    validate(instance=json_data, schema=json_schema)
    print("✅ test_required_properties: 验证通过")

打印:


2.7.2.7 依赖关系
  • dependentRequired 可以定义属性之间的依赖关系。例如,如果某个属性存在,则必须存在另一个属性。

示例:

json 复制代码
{
  "type": "object",
  "properties": {
    "creditCard": {
      "type": "string"
    },
    "billingAddress": {
      "type": "string"
    }
  },
  "dependentRequired": {
    "creditCard": [
      "billingAddress"
    ]
  }
}

代码:

python 复制代码
import requests
from jsonschema import validate

def test_dependent_required():
    """测试属性依赖关系"""
    json_data = {
        "username": "zhagnsan",
        "age": 18,
        "height": 175,
        "gender": "female",
        "hobby": {
            # "aaa": "aaa",
            # "bbb": "bbb"
        }
    }
    schema = {
        "type": "object",
        "properties": {
            "username": {"type": "string"},
            "age": {"type": "number"},
            "height": {"type": "number"},
            "gender": {"type": "string"},
            "hobby": {
                "type": "object",
                "properties": {
                    "aaa": {"type": "string"},
                    "bbb": {"type": "string"}
                },
                "dependentRequired": {  # hobby 对象内的依赖
                    "aaa": ["bbb"]
                }
            }
        },
        "dependentRequired": {  # 顶层对象的依赖
            "age": ["height", "gender"]
        }
    }
    validate(instance=json_data, schema=schema)
    print("✅ test_dependent_required: 验证通过")

# 如果 json_data 中只有 "age": 18 而没有 "height" 和 "gender",验证会失败。

打印:

相关推荐
天才测试猿2 小时前
Postman常见问题及解决方法
自动化测试·软件测试·python·测试工具·职场和发展·接口测试·postman
wtsolutions2 小时前
Sheet-to-Doc 支持 JSON 和 JSONL 格式:批量生成 Word 文档的新方式
json·word·wtsolutions·sheet-to-doc
Slow菜鸟5 小时前
Java基础 | JSON 处理手册
java·开发语言·json
流星白龙21 小时前
9.测试报告allure
接口测试
小鸡吃米…1 天前
Python - JSON
开发语言·python·json
少云清2 天前
【接口测试】7_Postman _Postman参数化
测试工具·接口测试·postman·参数化
流星白龙2 天前
5.接口自动化测试(4)
接口测试
武藤一雄2 天前
一款基于WPF开发的BEJSON转换工具
windows·c#·json·wpf