測試工作中往往需要對服務端所返回的Json數據做容錯,即需要確保原數據中各項值被替換成異常數據類型時,相關數據傳輸與處理系統不會發生報錯、崩潰等問題。
若手動編寫容錯數據,小編認為有以下兩點弊端:
1. 繁瑣操作帶來的人力、時間成本消耗;
2. 可能因數據繁多而導致疏漏;
因此希望實現能夠根據待測試Json數據,一鍵輸出全部相關容錯數據文件的腳本。
開始代碼實現之前希望能夠明確思路,小編經過思考,確立腳本實現環節如下:
1. 獲取key
獲取Json中所有需做數據替換處理的元素標識(如Json對象中的各個key);
2. 定位value
根據獲取到的標識,定位到需修改的值(如key對應的value);
3. 替換與輸出
將每個值進行數據替換並輸出為各式容錯數據文件。
1. 獲取key
以這樣一份基本包含各式數據的Json為例:
{ "testDict":{ "testDict_1_string":"1_value", "testDict_2_int":1, "testDict_3_bollen":false, "testDict_4_list":["4_value",1], "testDict_5_null":null, "testDict_6_dict":{"6_key":{"6_key_1":"6_value_1"}, "6_list":["test_list"]}, "testDict_7_complex":[ { "id":"10000", "testA":{"A":"A_value"}, "testB":["B1","B2"] }, { "id":"10001", "testC":{"C":"C_value"}, "testRepeat":"R_value" }, ["testX", "testY", {"testRepeat":"testRepeat"}], ["test_list_2"], "7_value" ], "testRepeat":"R_value" }, "testRepeat":"R_value", "test_extra":["test_extra_value"]}小編嘗試通過對其進行遞歸處理進行key的獲取,並輔以這樣幾點思考:
1. 針對數據中字典形式的json對象、列表形式的json數組,需不同的處理方法;
2. 為避免重複key混淆,需使用數據鏈路結構進行區分,如「父級key—子級key—子級key」;
3. 為避免鏈路結構同key產生混淆,需使用特殊符號進行層級連結。
4. 為避免多重數組導致數據鏈路結構重複,需額外添加」inlist」標識。
代碼如下:
def getKeyFromJsonFile(dic_json, keylist, keyParent=None, isChild=False, listInlist=False): if isinstance(dic_json, dict): for key in dic_json: if isinstance(dic_json[key], dict): if isChild: key = keyParent + '-*-' + key keylist.append(key) getKeyFromJsonFile(dic_json[key.split('-*-')[-1]], keylist, keyParent=key, isChild=True, listInlist=False) elif isinstance(dic_json[key], list): if isChild: key = keyParent + '-*-' + key keylist.append(key) for i in dic_json[key.split('-*-')[-1]]: getKeyFromJsonFile(i, keylist, keyParent=key, isChild=True, listInlist=False) else: if listInlist: key = key + '_*inlist' if isChild: key = keyParent + '-*-' + key keylist.append(key) if isChild and isinstance(dic_json, list): for i in dic_json: getKeyFromJsonFile(i, keylist, keyParent=keyParent, isChild=True, listInlist=True)2. 定位value
小編嘗試將每個key值以連結符號-*-進行分割為列表,並於Json數據中逐級進行找尋、定位,此時對這樣兩種情況進行了考慮。
若key值對應的value類型並非列表,則位於鏈路末端的key值對應的value即是需要修改的值:
def getValue(slist, data_next): for j in range(0 ,len(slist)): if isinstance(data_next[slist[j]], list): return if j == len(slist)-1: value = data_next[slist[j]] return data_next = data_next[slist[j]]而列表內元素無法根據key值定位,直接定位到列表後續進行遍歷即可:
def getValueFromList(data_list, key_list): if isinstance(data_list, dict): for key in key_list: if key in data_list.keys() and key == key_list[-1]: value = data_list[key] if isinstance(data_list[key], list): value = data_list[key] return elif key in data_list.keys(): getValueFromList(data_list[key], key_list)二者結合,則getValue方法內列表相關邏輯應是:
if isinstance(data_next[slist[j]], list): # 當前key無子節點 if j == len(slist)-1: # 得到需要遍歷其內元素進行修改的目標列表 value = data_next[slist[j]] # 截取後續子節點在列表中進行遞歸 else: for datas in data_next[slist[j]]: tlist = slist[j+1:] getValueFromList(datas, tlist) return針對列表處理方法getValueFromList,小編還進行了以下補充(此處代碼不再贅述):
1. 針對列表中包含列表,需添加判斷isinstance(data_list, list)繼續遞歸處理;
2. 針對添加了inlist的列表標識,需進行字符串分割後再去遍歷取值。
3. 替換與輸出
通過遍歷預設的測試數據列表即可對需要修改的值進行替換,列表示例如下:
null = Nonefalse = Falsetype_list = ["testString", 1, false, null, ["test_list"], {"test_dict":"test_dict_value"}]修改後的數據指向的仍是原待測試Json數據(需要在每次修改、輸出文件後進行數據還原),直接將其寫入文件即可——將以容錯類型命名的每組數據存入以數據鏈路key值命名創建的文件夾內(避免輸出相同結構的重複數據):
with open(path, "w") as f: json.dump(data, f, sort_keys=True, indent=4, ensure_ascii=False)此外,預設(如Json數據中不存在這一key)同樣是一種常規的數據容錯方式,可使用pop()方法操作字典、列表對相應值進行刪除予以實現。
綜上,運行腳本可得容錯文件如圖——針對需要替換的值,每組容錯數據包含int、string、bool等數據類型及數據預設:
打開任一文件,如圖中...-testA-*-A_int.json,可見原數據中相應值已被替換成了預設值:
"testDict_7_complex": [ { "id": "10000", "testA": { "A": 1 },至此,一鍵自動化輸出Json容錯數據文件的目的便達成了。感謝閱讀,歡迎交流。
基於python的測試報告自動化生成
搜狗測試微信號:Qa_xiaoming
搜狗測試QQ粉絲群:459645679