天天看點

python自動化測試-用于檢查嵌套json包含關系需求:代碼實作

需求:

有兩個json檔案。兩個都是複雜嵌套格式。需要比對A.json裡是否包含b.json。

例如A.json是

{
  "role": "admin",
  "routes": [
    "/Home",
    "/DeviceManagement",
    "/UserManagement"
  ]
}      

B.json是

{
  "role": "admin",
  "routes": [
    "/Home",
    "/TemplateManagement",
    "/DataDictionary",
    "/ClassifyAndSubEntry",
    "/ProjectManagement",
    "/DeviceManagement",
    "/UserManagement"
  ]
}      

要檢查B檔案是否包含A檔案。這個json檔案還好嵌套不多,當多個dict和list魂用,即[]和{}太多時,則會出現很難比對的問題。我考慮使用jsonpath來解決這個問題

代碼實作

1.把json檔案變成一個新的dict[jsonpath,value] ,例如’infos/0/item’: ‘direction’  表示jsonpath為”infos.0.item”對應的值是direction。具體的可以列印一下JsonPathValue這個類的final_dict就能明白了

#  filename : test1.py
#  description :
#
#  created by zhenwei.li at 2019/5/27 10:59
import json
class JsonPathValue(object):
    def __init__(self, datadict):
        self.stack = []
        self.final_dict = {}
        self.do_walk(datadict)
    def get_dict(self):
        return self.final_dict
    def do_walk(self, datadict):
        if isinstance(datadict, dict):
            for key, value in datadict.items():
                self.stack.append(key)
                # print("/".join(self.stack))
                if isinstance(value, dict) and len(value.keys()) == 0:
                    self.final_dict["/".join(self.stack)] = "EMPTY_DICT"
                if isinstance(value, list) and len(value) == 0:
                    self.final_dict["/".join(self.stack)] = 'EMPTY_LIST'
                if isinstance(value, dict):
                    self.do_walk(value)
                if isinstance(value, list):
                    self.do_walk(value)
                else:
                    self.final_dict["/".join(self.stack)] = value
                self.stack.pop()
        if isinstance(datadict, list):
            n = 0
            for key in datadict:
                self.stack.append(str(n))
                n = n + 1
                if isinstance(key, dict):
                    self.do_walk(key)
                if isinstance(key, list):
                    self.do_walk(key)
                if isinstance(key, str):
                    self.final_dict["/".join(self.stack)] = key
                self.stack.pop()
def json_contain(checkpoint, actual, assert_flag):
    """
    檢查實際結果(json)中是否包含檢查點(json)。兩個必須是同種格式,比如同時是{}或者[]
    :param checkpoint: 檢查點(期望結果)
    :param actual:  實際結果
    :param assert_flag: 是否啟用assert檢查
    :return: 比對成功或失敗
    """
    result = False
    if isinstance(checkpoint, list):
        '''如果期望的檢查點是list[]格式,使用此方法檢查'''
        find_count = 0
        check_lenth = len(checkpoint)
        for item in checkpoint:
            checkpoint_dict = JsonPathValue(item).get_dict()
            if isinstance(actual, list):
                find_flag = False
                for actual_item in actual:
                    actual_dict = JsonPathValue(actual_item).get_dict()
                    find_flag = list_contain(checkpoint_dict, actual_dict, False)
                    if find_flag:
                        find_count += 1
                        break
                print(find_flag)
            else:
                assert False, "傳回的實際結果格式不正确"
            if assert_flag:
                assert find_flag, "期望結果中的\n%s\n比對失敗,實際結果是:\n%s" % (item, actual)
        if find_count == check_lenth:
            result = True
    elif isinstance(checkpoint, dict):
        '''
        如果期望的檢查點是dict{}格式
        '''
        checkpoint_dict = JsonPathValue(checkpoint).get_dict()
        actual_dict = JsonPathValue(actual).get_dict()
        if list_contain(checkpoint_dict, actual_dict, True):
            result = True
    return result
def list_contain(checkpoint_dict, actual_dict, assert_flag):
    """
     檢查實際結果(list)中是否包含期望結果(list)
    :param checkpoint_dict: 實際結果
    :param actual_dict: 期望結果
    :param assert_flag: 是否啟用assert檢查
    """
    result = set(checkpoint_dict.items()).issubset(set(actual_dict.items()))
    if assert_flag is True:
        different = set(checkpoint_dict.items()) - (set(actual_dict.items()))
        assert result, \
            "期望結果中的%s比對失敗,實際結果是:\n%s" % (different, actual_dict)
    return result
json_data = open('A.json', 'rb').read()
json_dict = json.loads(json_data)
json_data2 = open('B.json', 'rb').read()
json_dict2 = json.loads(json_data2)
res1 = json_contain(json_dict, json_dict2, True)
print(res1)