一般常规的接口返回值校验需要把需要校验的字段逐个进行断言判断,这样进行有很大的编码工作量,显然不适用于接口测试平台。可以看一下例子:
1import requests
2
3#查询发布会接口
4url = "http://127.0.0.1:8000/api/get_event_list/"
5
6r = requests.get(url, params={'eid':'1'})
7result = r.json()
8print(result)
9assert result['status'] == 200
10assert result['message'] == "success"
11assert result['data']['name'] == "锤子手机发布会"
12assert result['data']['address'] == "成都"
13assert result['data']['start_time'] == "2017-11-21T15:25:19"
一个接口的返回值中如果有5个关键值就需要写5句断言。
所以本次打算采用jsonschema
的方式进行接口结构的校验。
jsonschema是描述你的JSON数据格式;JSON模式(应用程序/模式+ JSON)有多种用途,其中之一就是实例验证。验证过程可以是交互式或非交互式的。例如,应用程序可以使用JSON模式来构建用户界面使互动的内容生成除了用户输入检查或验证各种来源获取的数据。 Json Schema 快速入门https://blog.csdn.net/silence_xiao/article/details/81303935
具体的编写规则请自行查阅相关文档。 JsonSchema相当于一种契约测试,约定一个约束,如果符合要求则通过,如果不符合就不通过。
契约测试https://www.jianshu.com/p/ec40734c872a
具体优势,请自行体会吧,毕竟谁断言谁知道。
虽然我们的要求应该是使用平台的人员传入一个自行编写的JsonSchema,然后我们进行结果的比对。但是这样的学习成本过高,并不很符合实际。所以这个契约的生成就需要进行一定的协助。
设计的思路为:用户传入一个认为正确的接口返回值,平台进行初步的类别判断并询问是否需要增加每个key值的约束。例如一个type
为number
的对象,是否需要增加最大值
,最小值
的校验。
现成的jsonschema转换器:https://jsonschema.net/#/
不过没有找到源码,只能自己实现一个了。
首先是格式的校验
1def to_jsonschema(self, json_data, result):
2 '''
3 递归生成jsonschema
4 '''
5 if isinstance(json_data, dict):
6 is_null = True
7 result.append('{')
8 result.append("'type': 'object',")
9 result.append("'additionalProperties': 'false',") # 不允许添加任何其他属性。
10 result.append("'required':[],") # 必需属性,先留空
11 result.append("'properties': {")
12 for k, v in json_data.items():
13 is_null = False
14 result.append("'%s':" % k)
15 self.to_jsonschema(v, result)
16 result.append(',')
17 if not is_null:
18 result.pop()
19 result.append('}')
20 result.append('}')
21 elif isinstance(json_data, list):
22 result.append('{')
23 result.append("'type': 'array',")
24 result.append("'items': ")
25 self.to_jsonschema(json_data[0], result)
26 result.append('}')
27 elif isinstance(json_data, float):
28 result.append("{")
29 result.append("'type': 'number'")
30 result.append('}')
31 elif isinstance(json_data, int):
32 result.append("{")
33 result.append("'type': 'integer'")
34 result.append('}')
35 elif isinstance(json_data, str):
36 result.append("{")
37 if json_data.upper() in ("TRUE", "FALSE"):
38 result.append("'type': 'boolean'")
39 else:
40 result.append("'type': 'string'")
41 result.append('}')
42 return "".join(result)
覆盖了:object
,array
,number
,boolean
,string
下面补全required
和增加限制条件
1def complement_required(self, jsonschema_dict):
2 """
3 补全必需属性
4 """
5 if isinstance(jsonschema_dict, dict):
6 for item, value in jsonschema_dict.items():
7 if value == 'object':
8 properties = jsonschema_dict.get("properties")
9 if isinstance(properties, dict):
10 for i, j in properties.items():
11 if j.get("type") in ("integer", "number", "string"):
12 self.complement_limit(i, j)
13 jsonschema_dict['required'].append(i)
14 if isinstance(j, dict) and j.get('type') == "object":
15 self.complement_required(j)
16 elif isinstance(jsonschema_dict, list):
17 for i in jsonschema_dict:
18 self.complement_required(i)
19
20def complement_limit(self, name, limit_dict):
21 for i in self.limit:
22 if name == i[0]:
23 limit_type = i[1]
24 if limit_type == 'integer' or limit_type == 'number':
25 if i[2]:
26 limit_dict["maximum"] = i[2]
27 if i[3]:
28 limit_dict["minimum"] = i[3]
29 if i[4]:
30 limit_dict["enum"] = i[4]
31 if i[5]:
32 limit_dict["multipleOf"] = i[5]
33 elif limit_type == 'string':
34 if i[2]:
35 limit_dict["maxLength"] = i[2]
36 if i[3]:
37 limit_dict["minLength"] = i[3]
38 if i[4]:
39 limit_dict["enum"] = i[4]
40 if i[5]:
41 limit_dict["pattern"] = i[5]
进行简单的测试:
测试
可以看到基本符合要求了,后续页面/接口传入正确的东西就可以自动生成了。
里面对array
的限制条件还有所欠缺,在后续补上。