zoukankan      html  css  js  c++  java
  • 9-2、大型项目的接口自动化实践记录----递归判断两个json串是否相等

    1、已知json串构成的情况下判断

      先构造一下场景,假设已经把各个数据都移除掉不对比的字段


                              图1

      预期、实际结果,复杂接口返回多层嵌套json时,同下


                              图2

      预期、实际结果值为:{child_json1:list1,child_json2:list2}

      其中list1、list2为child_json,值为:[dict1,dict2]

      其中dict1、dict2为child_child_json,最底层json,无嵌套,值为:{key1:value1,key2:value2}

      如果一开始就直接判断预期结果与实际结果一致,当list1、list2不一致时,会怎样呢,我们把list2做下修改,如下图


                              图3

      直接对他们进行判断


                              图4

      结果如下图,异常提示把整串的list抛出来了,当字段数多的时候,就比较难定位问题


                              图5

      如果对child_json这层开始判断,也是类似的,因此我们要从小的单元开始判断,即从child_child_json(即无嵌套的dict)开始判断。

      1)先判断child_child_json是否一致:直接用Dictionaries Should Be Equal,就可以

        假设取到了child_child_json_预、child_child_json_实,则判断如下:


                              图6

      PS:从上一篇,我们可以看到RF自带的Dictionaries Should Be Equal、Lists Should Be Equal在判断无嵌套的dict、list时,错误提示很清晰。

      2)如果所有child_child_json相等,再判断child_json(值为list)是否相等:用Lists Should Be Equal判断。

        ①先分别获取两个child_json的长度,并判断是否相等

        ②for循环,根据下标分别获取child_child_json,1)中的方法判断所有child_child_json是否相等

        ③最后判断两个child_json是否相等(本例中当所有child_child_json相等时,不需要这个也行)


                              图7

      3)如果child_json都相等,最后再判断预期、实际结果(值为dict)是否相等:用Dictionaries Should Be Equal判断。

        ①先分别获取json的keys,并判断是否一致

        ②for循环,根据key分别获取child_json,2)中的方法判断所有child_json是否相等

        ③最后判断两个json是否相等


                              图8

      分别看一下两个值一致和不一致的执行情况,一致时如下:


                              图9

      值不一致时,如下图,child_json2中第一个dict的key2的value不一样:


                              图10

      执行结果如下,发现离错误最近的path打印,值定位了index为0,没有定位到是child_json2,还需要往前找。


                              图11

      我们在前面判断child_json是否相等的方法2)中,做下修改,加一个${path}的参数,用于传父path


                              图12

      在case这边,把${key}作为参数传入


                                图13

      执行结果如下图,比较清晰的说明了是child_json2/0下的值不一致


                                图14

    2、其他构成格式的json串

      {"key1":"value1","child_json":[{"child_json_key1":"child_json_value1","child_child_json":[child_child_json_dict1,child_child_json_dict2]},child_json_dict2]}

      如上的格式,第一层的key,对应的value有普通字段,也有child_json,child_json为list,child_json下又有普通字段及嵌套的child_child_json,这种情况下,1中的代码就不适用了,因此要考虑下如何兼容各种格式的json串,总不能换一个格式的json串,就写一套判断方法。

      从1中的实现,可以看到,判断两个json串是否相等,我们的思路是:

        ①先初步判断:如果是dict,先判断他们的keys是否一致;如果是list,则先判断他们的长度是否一致

        ②如果json下有子json串(dict或list),找出子json串,对子json串进行判断

        ③重复①②,一直到最后一层json(底下没有dict或list)

        ④从最后一层的子json,一层一层往上进行判断,用Dictionaries Should Be Equal或Lists Should Be Equal判断是否相等。

        PS:过程中加参数path,用于定位路径

        写成脚本:

        ①类型是dict或list,走对应的初步判断


                                图15

        加一下方法:判断dict_json串keys是否一致、判断list_json串长度是否一致


                                图16:判断dict_json串keys是否一致  

                                图17:判断list_json串长度是否一致

        当然,在这之前,要先获取json串是dict还是list


                                图18

        ②获取child_json,因为child_json可能存在0~N个,因此把它存为list


                                图19

                                图20

        加一下方法:遍历dict_json,获取child_jsons、遍历list_json,获取child_jsons


                                图21:遍历dict_json,获取child_jsons-1

                                图22: 遍历dict_json,获取child_jsons-2

                                图23:遍历list_json,获取child_jsons-1

                                图24: 遍历list_json,获取child_jsons-2

        再新加下方法:类型为dict或list的,以child_json1/child_json2/path,三个为一组的格式,加进child_jsons_list(这里三个值也可以拼成list再加)


                                图25:类型为dict或list的,加进child_jsons_list

        ③通过for循环,一个一个对child_json进行判断


                                图26

      要重复①②的步骤,所以就有这么一个过程:初步判断->找子json->初步判断->找子json->初步判断->找子json……->找不到子json时进行后续的操作

      有点类似于故事:从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山...

      区别点在于故事是无限循环,没有结束的事件,而我们的过程有个结束的标志:找不到子json。因此我们这里可以用递归来实现。

      先拿故事,来说明下递归的实现,先看下循环实现,这里只设置30次


                                图27

      结果如下


                  图28

      递归实现:先封装个方法:山、庙、和尚、故事,方法内容如下


                  图29

      到了和尚讲故事后,要做的事情 跟方法里的事情一样,那么可以调用方法自己


                图30

      那么当用例运行方法“山、庙、和尚、故事”,会先运行1~4行,到第5行的时候,又运行方法“山、庙、和尚、故事”,又再运行1~4行,然后再运行方法“山、庙、和尚、故事”……因为没有跳出的结束标志,因此就会无限循环运行,结果如下:

      PS:报错为RF设置的递归阙值,递归的方法运行次数达到阙值时就报错。


                        图31

      回过来看我们的json串对比③,它跟故事类似,因此我们也可以用递归的方法,区别在于要有结束的标志。

      新建一个方法:判断两个json是否相等

      方法前面即为前面①②实现的内容


                                    图32

      获取到子json后,子json又重复前面的步骤,如下图在for循环下,运行方法自己:则可以一直重复①②,直到找不到子json,${child_jsons_list}为空,for循环跳过,不再运行方法自己。


                                    图33

      ④找不到子json后,开始判断当前节点的json串是否相等


                                    图34

      方法:断言两个dict或list相等


                                    图35

      假设最后一层jsons是json_last,那么倒二层可能是这样的[json_last1,json_last2],也有可能是{"key1":"value1","json_last":json_last}

      在倒二层for循环中,运行方法”判断两个json是否相等“,把所有的json_last判断完后,则for循环执行结束,开始执行方法“断言两个dict或list相等”,即判断倒二层的json是否相等。

      以此类推,会逐层往上,完整的判断整个json。

      以上,实现了递归判断两个json串是否相等,里面具体的提示可以优化,也可以增加入参,对指定节点进行判断,还有这么判断非常耗时,在自动化中可以在前面先直接用should be equal来判断,不等时再执行该方法调试错误。可优化的东西比较多,这里就不一一写了。

    上一篇  9-1、大型项目的接口自动化实践记录----数据库结果、JSON对比

  • 相关阅读:
    oracle 分析函数3
    oracle 分析函数4
    oracle 分析函数2
    postgres
    博客系统
    Java 笔试面试 算法编程篇 一
    Java 笔试面试 基础篇 一
    Struts2
    mysql 数据类型
    ExceptionDemo
  • 原文地址:https://www.cnblogs.com/walkingtester/p/11280819.html
Copyright © 2011-2022 走看看