如何在pytest接口自动化框架中扩展JSON数据解析功能?

🍅 视频学习:文末有免费的配套视频可观看

🍅 关注公众号【互联网杂货铺】,回复 1 ,免费获取软件测试全套资料,资料在手,涨薪更快

本期内容就json格式的数据解析,来进行阐述。在MeterSphere中,有两种方式可以进行json格式的数据维护。一种是使用他们自带的JsonSchema来填写key-value表单。另一种就是手写json。

手写json在日常工作中效率较低,原因有二,一是手写太麻烦,占据大量个工作时间,影响效率。二是对正确性以及层级结构无法保证准确性。两者相比较,故选择JsonSchema的方式来维护json格式的数据。

json格式数据模型如下

"jsonSchema": {
      "properties": {
        "字段1": {
          "mock": {
            "mock": ""
          },
          "type": "string",
          "description": "字段描述。。。"
        },
        "字段2": {
          "type": "number",
          "mock": {
            "mock": ""
          },
          "minLength":50,
          "maxLength":100
        },
        "字段3": {
          "type": "integer",
          "mock": {
            "mock": ""
          },
          "description": "字段描述"
        }
      },
      "type": "object",
      "mock": {
        "mock": ""
      },
      "required": [
        "字段1",
        "字段2",
      ]
    }

使用JsonSchema作为最外层节点,第二层节点包含了类型、字段属性、必填字段列表等参数信息。第三层节点就是字段的一些属性,包含了字段长度、字段名称、字段类型、字段描述等

特别需要说明的是,MeterSphere的字段类型有很多,其中包含了object以及array这两种类型的数据

  • object:如果字段类型是object,那么该字段节点下会嵌套另外一些字段,这些字段也是json格式的
  • array:同理,如果字段类型是array,那么该字段下面会嵌套一个列表,列表中的每一个元素,都是json格式,不可以手动设置key,是从0递增自动命名。

这两种类型是可以无限重复套娃下去。只要你需要。

所以在解析这类数据时,我们就需要先解决这种层层嵌套的问题。

思路梳理

  • 首先判断一下数据类型是否为上述这种套娃格式
    • 判断字段类型是object还是array
    • 利用python的递归,调用自身。并将字段属性作为参数传给这个函数
  • 然后提取字段中的最大值,最小值,以及参数名称、类型
  • 判断当前字段是否在必填列表中,如果在,则将这个字段设置为必填

如上是大概的解题思路,抛开拆解套娃,代码相对简单。如下是源码展示

# 解析json请求的参数
def post_arguments(data, required_list=None):
    field = {}
    if not isinstance(data, dict):
        raise TypeError("'data' is not dict")
    for key, value in data.items():
        if value["type"] == "object" and "properties" in value:
            # 递归调用,实现多层嵌套解析
            if "required" in value:
                recursion_par = post_arguments(value["properties"], value["required"])
                par = {
                    key:
                        {"type": value["type"],
                         "description": value["description"] if "description" in value else "",
                         **recursion_par
                         }
                }
                field.update(par)
            else:
                recursion_par = post_arguments(value["properties"])
                par = {
                    key: {"type": value["type"],
                          "description": value["description"] if "description" in value else "",
                          **recursion_par
                          }
                }
                field.update(par)
        elif value["type"] == "array" and "items" in value:
            for l, i in enumerate(value["items"]):
                for arr_key, arr_value in i.items():
                    if arr_value == "object" and "properties" in arr_value:
                        # 递归调用,实现多层嵌套解析
                        if "required" in arr_value:
                            recursion_par = post_arguments(arr_value["properties"], value["required"])
                            par = {
                                l: {"type": value["type"],
                                    "description": value["description"] if "description" in value else "",
                                    **recursion_par
 
                                    }
                            }
                            field.update(par)
                        else:
                            recursion_par = post_arguments(arr_value["properties"])
                            par = {
                                l: {"type": value["type"],
                                    "description": value["description"] if "description" in value else "",
                                    **recursion_par
                                    }
                            }
                            field.update(par)
                    elif arr_value == "array" and "items" in arr_value:
                        if "required" in arr_value:
                            recursion_par = post_arguments(arr_value["properties"], arr_value["required"])
                            par = {
                                l: {"type": value["type"],
                                    "description": value["description"] if "description" in value else "",
                                    **recursion_par
                                    }
                            }
                            field.update(par)
                        else:
                            recursion_par = post_arguments(arr_value["properties"])
                            par = {
                                l: {"type": value["type"],
                                    "description": value["description"] if "description" in value else "",
                                    **recursion_par
                                    }
                            }
                            field.update(par)
                    else:
                        maxLength = MAX_LENGTH
                        minLength = MIN_LENGTH
                        required = "false"
                        if "maxLength" in arr_key:
                            maxLength = i["maxLength"]
                        elif "maxLength" in arr_key:
                            minLength = i["minLength"]
                        if required_list:
                            if l in required_list:
                                required = "true"
                        items_par = {
                            key:
                                {
                                    "type": value["type"],
                                    "description": value["description"] if "description" in value else "",
                                    l: {
                                        "type": i["type"],
                                        "required": required,
                                        "max": maxLength,
                                        "min": minLength
                                    }
                                }
                        }
                        field.update(items_par)
        else:
            maxLength = MAX_LENGTH
            minLength = MIN_LENGTH
            required = "false"
            if "maxLength" in value:
                maxLength = value["maxLength"]
            elif "minLength" in value:
                minLength = value["minLength"]
            if required_list:
                if key in required_list:
                    required = "true"
                else:
                    required = "false"
            par = {
                key: {
                    "type": value["type"],
                    "description": value["description"] if "description" in value else "",
                    "required": required,
                    "max": maxLength,
                    "min": minLength,
                }
            }
            field.update(par)
    return field
 

可以看到,思路不是很难,但是代码还是比较臃肿的,其中有很多的代码是冗余的,在后期优化中,将考虑这块重构一下。大家在写的时候将思路缕清,别写出我这么烂的代码。。。。引以为戒~

结语

总结一下这个函数

  • 首先在写的时候,多重嵌套是个难题,可以通过递归的方式解决
  • 另外一定在思路缕清的前提下,再开始写代码,我就是在边写边思考,一个for循环一个for循环的嵌套。导致代码极其臃肿。执行效率有一定程度的降低,且代码可读性不好
  • 公共代码提取:像一些数据结构模板,这些都可以提取成一个公共变量,然后调用即可。在函数中反复写着相类似的模板,是一种很愚蠢的行为。。。

同时,在这我为大家准备了一份软件测试视频教程(含面试、接口、自动化、性能测试等),就在下方,需要的可以直接去观看。

字节大佬,一周讲完,自动化测试项目实战,这套教程是怎么称霸B站的?【2024最新版】

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值