在进行接口自动化测试的时候,只是校验「状态码」或者「部分字段」并不能很好的发现问题,有时候需要对字段的类型,关系进行校验。
之前尝试过使用JSON Schema
来进行校验,但是语法上感觉比较变扭。这次尝试使用pydantic
来进行校验
https://pydantic-docs.helpmanual.io/
pydantic:使用 python 类型注释进行数据验证和设置管理。
$ pip install pydantic
最近在测试一个「订单合流」的接口
该接口可以查询制定类型的订单
总共有19个类型的订单,用一个字典处理它的对应关系
biz_type_data = {
1: "预约挂号",
2: "问诊",
3: "服务包",
4: "追问包",
5: "一病多问",
6: "会员",
7: "体检",
8: "远程医疗",
9: "处方",
10: "专病",
11: "商品",
12: "处方药品",
13: "会员拼团",
14: "讲堂课程",
15: "健康管家",
16: "赞赏",
17: "停诊保障",
18: "检查检验",
19: "心理体检",
}
该接口的请求参数为
data = {"q": "", "pageNo": 1, "pageSize": 10, "bizOrderTypes": [1]}
修改「bizOrderTypes」列表即可返回对应类型的订单
比如[1]
就是返回「预约挂号」的订单
返回的内容类似:
{
"code": "0",
"flag": "0",
"message": "成功",
"retUrl": "",
"pageNo": 1,
"pageSize": 1000,
"pageCount": 1,
"recordCount": 20,
"items": [
{
"bizNo": "202111171045333625",
"bizCode": "",
"bizName": "",
"bizOrderType": 1,
"bizOrderTypeName": "预约挂号",
"bizType": 1,
"bizTypeName": "普通预约单",
"title": "",
"num": 1,
"dealAmount": 1,
"bizStatus": 3,
"bizStatusName": "待确认",
"providerName": "",
"gmtBizCreated": 1637311540000,
"props": {
"patientName": "钟鑫",
"deptName": "神经外科",
"docName": "卢来元懿",
"insure": 0,
"visitDate": 1637337600000,
"docTitle": "国家专家",
"hospitalName": "微医门诊部"
}
},
{
"bizNo": "202111171045333406",
"bizCode": "",
"bizName": "",
"bizOrderType": 1,
"bizOrderTypeName": "预约挂号",
"bizType": 1,
"bizTypeName": "普通预约单",
"title": "",
"num": 1,
"dealAmount": 1000,
"bizStatus": 2,
"bizStatusName": "待就诊",
"providerName": "",
"gmtBizCreated": 1637311475000,
"props": {
"patientName": "钟鑫",
"deptName": "妇科",
"docName": "王涛",
"insure": 0,
"visitDate": 1637683200000,
"docTitle": "主任医师",
"hospitalName": "徐州市中医院"
}
}
],
"errorInfo": "成功"
}
from typing import Union, List
from pydantic import BaseModel, validator
from datetime import date
由于外部的内容是通用的页面处理,所以我们主要校验item
中的内容
class new_order_list(BaseModel):
bizNo: str
bizCode: str = ""
bizName: str = ""
bizOrderType: int
bizOrderTypeName: str
bizType: int
bizTypeName: str
title: str = ""
num: int
dealAmount: int
bizStatus: int
bizStatusName: str
providerName: str = ""
gmtBizCreated: date
props: dict
str
表示内容应该为字符串
str = ""
表示内容应该为字符串且默认为空
int
表示内容应该为数字
dict
表示内容应该为字典
data
表示时间
Pydantic支持以下日期时间 类型:
datetime
字段可以是:
datetime
, 现有datetime
对象
int
或float
,假定为 Unix 时间,即自 1970 年 1 月 1 日以来的秒数(如果 >=-2e10
或 <= `2e10`)或毫秒(如果 <`-2e10`或 >2e10
)
str
,以下格式有效:
YYYY-MM-DD[T]HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]]]
int
或float
作为字符串(假设为 Unix 时间)
date
字段可以是:
date
, 现有date
对象
int
或者float
,见datetime
str
,以下格式有效:
YYYY-MM-DD
int
或者float
,见datetime
time
字段可以是:
time
, 现有time
对象
str
,以下格式有效:
HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]]]
timedelta
字段可以是:
timedelta
, 现有timedelta
对象
int
或者float
,假设为秒
str
,以下格式有效:
[-][DD ][HH:MM]SS[.ffffff]
[±]P[DD]DT[HH]H[MM]M[SS]S
(timedelta 的 ISO 8601 格式)
由于props
不同订单返回的字典不一样,所以我们后面封装另一个类去校验它
对于某些字段有专门的逻辑,所以我们编写一个biz_type_match
函数去校验
@validator('bizType')
def biz_type_match(cls, v, values, **kwargs):
if "bizOrderType" in values and "bizTypeName" in values:
if values["bizOrderType"] == 1:
reg_type_name = ["普通预约单", "专病预约单"]
if reg_type_name[v - 1] != values["bizTypeName"]:
raise ValueError('bizType与bizTypeName不一致')
return v
这个函数中v
表示装饰器装饰的内容,也就是bizType
values
表示的返回的整个内容
所以我们就可以校验「bizTypeName」和「bizType」的对应关系了
class bizType():
class bizType1(BaseModel):
"""
预约挂号
"""
deptName: str # 科室名称
patientName: Union[str, None] # 患者姓名 就诊人可以解绑,所以允许为空
docName: str # 医生姓名
docTitle: str # 医生职称
visitDate: date # 就诊日期时间戳
hospitalName: str # 医院名称
insure: int # 是否购买停诊保险 0否1是
Union
表示运行多个类型,可以根据具体逻辑设计
for i in response_data['items']:
new_order_list(**i)
obj = getattr(bizType, f'bizType{type_data[0]}')
try:
obj(**i['props'])
except Exception as e:
pytest.assume(False, f"Error:{e}")
将拿到的数据传入对应的类中,就会自动进行校验
更多校验方式可以参考官网:https://pydantic-docs.helpmanual.io/