由来:
接口中基础的边界和数据类型,验证必不可少,但工作量又很大,为了把这块内容的工作时间缩短,所以有了此想法
实现思路如下:
# 根据参数名,指定参数规则,生成对应的参数化信息
# "name": [{"必填项": True},{"长度": [2,10]},{'字符类型':['汉字','英文','特殊字符']}]
# 轮询取值,根据设定的值,自动生成相应的基础数据
# 长度:最小长度-1(为0时是None)、最小长度、最大长度、最大长度+1
# 字符类型: 汉字、字母、特殊字符、数字、字符混合
# 必填项
# 生成两批数据,一批异常范围,一批正常范围
a = {"name": [{"required": True}, {"lengthRule": [2, 10]}, {'strType': ['汉字', '英文', '特殊字符']}],
'id': [{"required": True}, {"lengthRule": [2, 10]}, {'strType': ['数字']}]}
print(makeCaseData(a))
"""
[{'failInfo': [[[{'id': '9'}], [{'id': '96666666666'}], [{'id': ' '}], {'id': None}], [[{'name': '伪'}], [{'name': '伪文文文文文文文文文文'}], [{'name': ' '}], {'name': None}], [[{'name': 'u'}], [{'name': 'uLLLLLLLLLL'}], [{'name': ' '}], {'name': None}], [[{'name': '"'}], [{'name': '"\\\\\\\\\\'}], [{'name': ' '}], {'name': None}]]}, {'succssInfo': [[[{'id': '90'}], [{'id': '9111111111'}]], [[{'name': '伪中'}], [{'name': '伪文文文文文文文文文'}]], [[{'name': 'ux'}], [{'name': 'uaaaaaaaaa'}]], [[{'name': '";'}], [{'name': '""""""""""'}]]]}]
具体代码实现
from random import choice
dataDicTemp = {
"小写字母": 'abcdefghijklmnopqrstuvwxyz',
"大写字母": 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
"英文": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
"数字": '0123456789',
"特殊字符": """!"#$%&'()*+,-./:;<=>?@[]^_`{|}~""",
"汉字": "中文伪造数据"
}
class FakerStringData():
def __init__(self, tagkey, stryType, lengthRule, required=True):
self.tagkey = tagkey
self.stryType = stryType
self.required = required
try:
assert self.stryType in dataDicTemp.keys()
except Exception:
raise Exception("需要的数据类型:%s,不在模板范围内:%s,请确认数据类型" % (stryType, dataDicTemp.keys()))
self.tempData = choice(dataDicTemp[self.stryType]) # 随机取样本数据中1个长度
self.maxLenth = lengthRule[1]
self.minLenth = lengthRule[0]
def _lengthRule(self):
''' LTT 20210326
#生成最小长度-1(为0时是None)、最小长度、最大长度、最大长度+1数据
:param targkey: 目标key值
:param textTemp: 填充的信息模板值
:param min: 最小长度
:param max: 最大长度
:return: [{'a': None}, {'a': 'J'}, {'a': 'JAA'}, {'a': 'JAAA'}]
'''
finalInfo = {}
if self.minLenth - 1 > 0:
preMinInfo = self.tempData.ljust(self.minLenth - 1,
choice(dataDicTemp[
self.stryType])) # 比最小长度少一位
else:
preMinInfo = None
minInfo = self.tempData.ljust(self.minLenth, choice(dataDicTemp[self.stryType])) # 最小长度
maxinfo = self.tempData.ljust(self.maxLenth, choice(dataDicTemp[self.stryType])) # 最大长度
aftMaxInfo = self.tempData.ljust(int(self.maxLenth) + 1, choice(dataDicTemp[self.stryType])) # 比最大长度多一位
# 合法数据,格式勿变,符合ddt中data参数数据形式要求
finalInfo["succssInfo"] = [[{self.tagkey: minInfo}], [{self.tagkey: maxinfo}]]
# 非法数据,格式勿变,符合ddt中data参数数据形式要求
failInfo = [[{self.tagkey: preMinInfo}], [{self.tagkey: aftMaxInfo}],
[{self.tagkey: " " * self.maxLenth}]]
if self.required == True:
# 生成必填项数据为None的 非法数据
failInfo += [{self.tagkey: None}]
finalInfo["failInfo"] = failInfo
return finalInfo
def makeCaseData(paramsDict):
'''
根据参数规则,生成相应的case用例数据
:param paramsDict: 接口参数规则 eg {"name": [{"required": True}, {"lengthRule": [2, 10]}, {'strType': ['汉字', '英文', '特殊字符']}],
'id': [{"required": True}, {"lengthRule": [2, 10]}, {'strType': ['数字']}]
}
:return: 符合接口逻辑的case数据
'''
finalInfo = []
for tagKey, rules in paramsDict.items():
for rule in rules:
if rule.__contains__("required"):
requiredRule = rule['required']
elif rule.__contains__("lengthRule"):
lengthRule = rule['lengthRule']
elif rule.__contains__("strType"):
strType = rule['strType']
for typeName in strType:
info = FakerStringData(tagkey=tagKey, stryType=typeName, lengthRule=lengthRule,
required=requiredRule)._lengthRule()
finalInfo.append(info)
# 合并相同key的数据
dic = {}
for info in finalInfo:
for k, v in info.items():
dic.setdefault(k, []).append(v)
return [{k: v} for k, v in dic.items()]