05. 全量字段校验
2024年10月28日大约 8 分钟
05. 全量字段校验
1. 全量字段校验
概念
- 校验接⼝返回响应结果的全部字段(更进一步的断言)
接口校验思考
- 接口相应校验哪些字段?
- 客户端或其他服务使用的字段
- 需要校验字段的哪些内容?
- 字段名、字段值、字段类型
- 接口相应校验哪些字段?
校验内容
字段名
字段值或字段类型
校验流程(实现思路)
定义接口返回数据的期望格式
与接口实际响应数据对比校验
2. JSON Schema介绍
1. Json Schema
- 用来定义json数据约束的一个标准
2. 安装jsonschema
pip install jsonschema -i https://pypi.douban.com/simple/
查验:
pip 查验:pip list 或 pip show jsonschema
pycharm 中 查验:file --- settings --- 项目名中查看 python 解释器列表
3. 入门案例
{
"type": "object",
"properties": {
"success": {"type": "boolean"},
"code": {"type": "integer"},
"message": {"type": "string"}
},
"required": ["success", "code", "message"]
}
4. 校验方式
在线校验
http://json-schema-validator.herokuapp.comhttps://www.jsonschemavalidator.net 【推荐】
python代码实现校验
- 下章节
3. python实现JSON数据校验
1.实现步骤
导包 import jsonschema
定义 jsonschema格式、数据校验规则
调⽤ jsonschema.validate(instance="json数据", schema="jsonshema规则")
jsonschema.validate(instance, schema) """ instance:要验证的JSON数据 schema:用于校验JSON数据的验证规则 说明: 1. 该函数首先验证所提供的schema本身是否有效,然后再验证json数据 2. 如果schema模式本身是无效的,则抛出 jsonschema.exceptions.SchemaError 异常 2. 如果JSON数据校验不通过,则抛出 jsonschema.exceptions.ValidationError 异常 """
2. 查验校验结果
- 校验通过:返回 None
- 校验失败
- schema 规则错误,返回 SchemaError
- json 数据错误,返回 ValidationError
# 1. 导包
import jsonschema
# 2. 创建 校验规则
schema = {
# type: 类型
"type": "object",
# 配置信息:该关键字的值是一个对象, 对象中每个字段的校验规则, 用于type值为object的场景,type关键字的辅助
"properties": {
"success": {
"type": "boolean"
},
"code": {
"type": "integer"
},
"message": {
"type": "string"
}
},
# 配置必传参数
"required": ["succe1ss", "code", "message"]
}
# 准备待校验数据
data = {
"success": True,
"code": 10000,
"message": "操作成功"
}
# 3. 调用 validate 方法,实现校验
result = jsonschema.validate(instance=data, schema=schema)
print("result =", result)
# None: 代表校验通过
# ValidationError:数据 与 校验规则不符
# SchemaError: 校验规则 语法有误
4. JSON Schema语法
1. JSON Schema重点关键字
关键字 | 描述 |
---|---|
type | 表示待校验元素的类型 |
properties | 定义待校验的JSON对象中,各个key-value对中value的限制条件,用于type值为object的场景,type关键字的辅助 |
required | 定义待校验的JSON对象中,必须存在的key |
const | JSON元素必须等于指定的内容 |
pattern | 使用正则表达式约束字符串类型数据 |
2. 关键字详解-type
用于限定待校验JSON元素所属的数据类型
type取值 | 对应的python数据类型 | 描述 |
---|---|---|
object | object | 对象 |
array | list | 数组 |
integer | int | 整数 |
number | float或int | 数字 |
null | None | 空 |
boolean | bool | 布尔 |
string | str | 字符串 |
# 准备校验规则
schema = {
"type": "object"
}
# 准备数据
data = {"a": 1, "b": 2}
# 调用函数
res1 = jsonschema.validate(instance=data, schema=schema)
print(res1)
3. 关键字详解-properties
定义待校验的JSON对象中包含的字段
说明:是 type关键字的辅助。用于 type 的值为 object 的场景
该关键字的值是一个对象
当type取值为object时使用
用于指定JSON对象中的各种不同key应该满足的校验逻辑
作用:指定 对象中 每个字段的校验规则。 可以嵌套使用。
语法
{
"type": "object",
"properties":{
"字段名1":{规则},
"字段名2":{规则},
......
}
}
import jsonschema
# 准备校验规则
schema = {
"type": "object",
"properties": {
"success": {"type": "boolean"},
"code": {"type:": "integer"},
"message": {"type": "string"},
"money": {"type": "number"},
"address": {"type": "null"},
"data": {"type": "object"},
"luckyNumber": {"type": "array"}
}
}
# 准备测试数据
data = {
"success": True,
"code": 10000,
"message": "操作成功",
"money": 6.66,
"address": None,
"data": {
"name": "tom"
},
"luckyNumber": [6, 8, 9]
}
# 调用方法进行校验
res = jsonschema.validate(instance=data, schema=schema)
print(res)
import jsonschema
# 准备校验规则
schema = {
"type": "object",
"properties": {
"success": {"type": "boolean"},
"code": {"type:": "integer"},
"message": {"type": "string"},
"money": {"type": "number"},
"address": {"type": "null"},
"data": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"height": {"type": "number"}
}
},
"luckyNumber": {"type": "array"}
}
}
# 准备测试数据
data = {
"success": True,
"code": 10000,
"message": "操作成功",
"money": 6.66,
"address": None,
"data": {
"name": "tom",
"age": 18,
"height": 1.78
},
"luckyNumber": [6, 8, 9],
"a": 12
}
# 调用方法进行校验
res = jsonschema.validate(instance=data, schema=schema)
print(res)
4. 关键字详解-required
作用:校验对象中必须存在的字段。字段名必须是字符串,且唯⼀
**语法 **
{
"required": ["字段名1", "字段名2", ...]
}
import jsonschema
# 测试数据
data = {
"success": True,
"code": 10000,
"message": "操作成功",
"data": None
}
# 校验规则
schema = {
"type": "object",
"required": ["success", "code", "message", "data"]
}
# 调用方法校验
res = jsonschema.validate(instance=data, schema=schema)
print(res)
5. 关键字详解-const
作用:校验字段值是⼀个固定值
语法:
{
"字段名":{"const": 具体值}
}
import jsonschema
# 测试数据
data = {
"success": True,
"code": 10000,
"message": "操作成功",
"data": None,
}
# 校验规则
schema = {
"type": "object",
"properties": {
"success": {"const": True},
"code": {"const": 10000},
"message": {"const": "操作成功"},
"data": {"const": None}
},
"required": ["success", "code", "message", "data"]
}
# 调用方法校验
res = jsonschema.validate(instance=data, schema=schema)
print(res)
6. 关键字详解-pattern
作用:指定正则表达式,对字符串进行模糊匹配
基础正则举例:
1. 包含字符串:hello 如:nihao hello world
2. 以字符串开头 ^: ^hello 如:hello,world
3. 以字符串结尾 $: hello$ 如:中国,hello
4. 匹配[]内任意1个字符[]: [0-9]匹配任意⼀个数字 [a-z]匹任意一个小写字母 [cjfew9823]匹配任意一个
5. 匹配指定次数{}: [0-9]{11}匹配11位数字。
6. 匹配手机号:^[0-9]{11}$
语法:
{
"字段名":{"pattern": "正则表达式"}
}
import jsonschema
# 测试数据
data = {
"message": "!jeklff37294操作成功43289hke",
"mobile": "15900000002"
}
# 校验规则
schema = {
"type": "object",
"properties": {
"message": {"pattern": "操作成功"},
"mobile": {"pattern": "^[0-9]{11}$"}
}
}
# 调用方法校验
res = jsonschema.validate(instance=data, schema=schema)
print(res)
5. 综合案例
"""
综合案例
# properties: properties:定义待校验的JSON对象中包含的字段
# 说明: 是 type关键字的辅助。用于 type 的值为 object 的场景。
# 作用: 指定 对象中 每个字段的校验规则。 可以嵌套使用。
# required: 定义待校验的JSON对象中,必须存在的key
# 作用: 校验对象中必须存在的字段。字段名必须是字符串,且唯⼀
# const: JSON元素必须等于指定的内容
# 作用: 校验字段值是⼀个固定值。
# pattern: 使用正则表达式约束字符串类型数据
# 作用: 指定正则表达式,对字符串进行模糊匹配
# 基础正则举例:
# 1 包含字符串: hello
# 2 以字符串开头 ^: ^hello 如: hello,world
# 3 以字符串结尾 $: hello$ 如: 中国 ,hello
# 4 匹配[]内任意1个字符[]: [0-9]匹配任意⼀个数字 [a-z]匹任意一个小写字母 [cjfew9823]匹配任意一个
# 5 匹配指定次数{}: [0-9]{11}匹配11位数字。
# 6 匹配 手机号: ^[0-9]{11}$
"""
# 测试数据
import jsonschema
data = {
"success": False,
"code": 10000,
"message": "xxx登录成功",
"data": {
"age": 20,
"name": "lily"
}
}
# 校验规则
schema = {
"type": "object",
"properties": {
"success": {"type": "boolean"},
"code": {"type": "integer"},
"message": {"pattern": "登录成功$"},
"data": {
"type": "object",
"properties": {
"name": {"const": "lily"},
"age": {"const": 20}
},
"required": ["name", "age"]
}
},
"required": ["success", "code", "message", "data"]
}
# 调用测试方法
res = jsonschema.validate(instance=data, schema=schema)
print(res)
代码路径:test_code\ag_apiAutoTestFrameWorkIhrm
6. ihrm剩余
1. 使用全量字段校验
import unittest
import jsonschema
from api.ihrm_emp_crud import IhrmEmpCRUDAPI
from common.assert_util import assert_util
from common.db_util import DBUtil
from common.get_header import get_header
from config import TEL
class TestEmpAdd(unittest.TestCase):
"""添加员工测试"""
# header = {
# "Content-Type": "application/json",
# "Authorization": "Bearer 272150b5-7b7d-4509-9ee1-b15bbdc936a9"
# }
header = None
@classmethod
def setUpClass(cls) -> None:
cls.header = get_header()
def setUp(self) -> None:
# 删除手机号
delete_sql = f"delete from bs_user where mobile = '{TEL}'"
DBUtil.uid_db(delete_sql)
def tearDown(self) -> None:
# 删除手机号
delete_sql = f"delete from bs_user where mobile = '{TEL}'"
DBUtil.uid_db(delete_sql)
# 必选参数
def test01_add_emp(self):
self._testMethodName = "必选参数"
self._testMethodDoc = "[]"
# 准备数据
json_data = {
"username": "业务猪001",
"mobile": TEL,
"workNumber": "9527"
}
# 调用自己封装的 接口
resp = IhrmEmpCRUDAPI.add_emp(self.header, json_data)
print("添加-必选:", resp.json())
# 断言
# assert_util(self, resp, 200, True, 10000, "操作成功")
# 使用全量字段校验,替换断言
# 断言:校验响应状态码
self.assertEqual(200, resp.status_code)
# 校验规则
schema = {
"type": "object",
"properties": {
"success": {"const": True},
"code": {"const": 10000},
"message": {"pattern": "操作成功"},
"data": {"type": "object"}
},
"required": ["success", "code", "message", "data"]
}
# 调用jsonschema校验函数
jsonschema.validate(instance=resp.json(), schema=schema)
# 组合参数
def test02_add_emp(self):
self._testMethodName = "组合参数"
self._testMethodDoc = "[]"
# 准备数据
json_data = {
"username": "业务猪001",
"mobile": TEL,
"workNumber": "9527",
"formOfEmployment": "2"
}
# 调用自己封装的 接口
resp = IhrmEmpCRUDAPI.add_emp(self.header, json_data)
print("添加-组合:", resp.json())
# 断言
assert_util(self, resp, 200, True, 10000, "操作成功")
# 全部参数
def test03_add_emp(self):
self._testMethodName = "全部参数"
self._testMethodDoc = "[]"
# 准备数据
json_data = {
"username": "大猪乔治",
"mobile": TEL,
"timeOfEntry": "2021-12-01",
"formOfEmployment": 1,
"workNumber": "777888",
"departmentName": "测试",
"departmentId": "1452603344685203456",
"correctionTime": "2021-12-30T16:00:00.000Z"
}
# 调用自己封装的 接口
resp = IhrmEmpCRUDAPI.add_emp(self.header, json_data)
print("添加-全部:", resp.json())
# 断言
assert_util(self, resp, 200, True, 10000, "操作成功")
if __name__ == '__main__':
unittest.main()
2. 日志的使用
1. 将包含init_log_config()函数的日志文件,存放到项目目录 common/ 下。
2. 在项目入口文件中, 调用 init_log_config() 函数,指定日志文件名,及其他参数。
3. 在所有需要打印输出的 ,将logging.级别() 替换 调用 print 输出!
4. 去生成的日志文件中,查看日志信息。
也可以使用loguru
3. 构造员工id
1. 测试查询员工接口前(setUp),保证使用的员工id已存在!使用 insert SQL语句插入一个员工id
2. 使用这个员工id,进行查询员工接口测试
3. 测试查询员工接口结束(tearDown)时,删除这个员工id
import unittest
from api.ihrm_emp_curd import IhrmEmpCURD
from common.db_util import DBUtil
from common.get_header import get_header
"""
构造员工id
1. 测试查询员工接口前(setUp),保证使用的员工id已存在!使用insert SQL语句 插入一个员工id
2. 使用这个员工id,进行查询员工接口测试
3. 测试查询员工接口结束(tearDown)时,删除这个员工id
"""
class TestEmpQuery(unittest.TestCase):
header = None
@classmethod
def setUpClass(cls) -> None:
cls.header = get_header()
def setUp(self) -> None:
insert_sql = "insert into bs_user(id, mobile, username) values('11232738248634', '13974837801', '随便打打');"
DBUtil.uid_db(insert_sql)
def tearDown(self) -> None:
delete_sql = "delete from bs_user where id = '11232738248634';"
DBUtil.uid_db(delete_sql)
# 测试查询员工
def test01_query_emp(self):
# 使用数据库切实存在的 emp_id 传入
resp = IhrmEmpCURD.query_emp("11232738248634", self.header)
print("查询员工:", resp.json())