国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

可以做推廣的門戶網(wǎng)站軟件開發(fā)工資一般多少

可以做推廣的門戶網(wǎng)站,軟件開發(fā)工資一般多少,最新注冊公司流程及費(fèi)用,wordpress 拉不到底1.pytest數(shù)據(jù)參數(shù)化 假設(shè)你需要測試一個(gè)登錄功能,輸入用戶名和密碼后驗(yàn)證登錄結(jié)果??梢允褂脜?shù)化實(shí)現(xiàn)多組輸入數(shù)據(jù)的測試: 測試正確的用戶名和密碼登錄成功 測試正確的用戶名和錯(cuò)誤的密碼登錄失敗 測試錯(cuò)誤的用戶名和正確的密碼登錄失敗 測試錯(cuò)誤的用戶名和密碼登…

1.pytest數(shù)據(jù)參數(shù)化

????????假設(shè)你需要測試一個(gè)登錄功能,輸入用戶名和密碼后驗(yàn)證登錄結(jié)果??梢允褂脜?shù)化實(shí)現(xiàn)多組輸入數(shù)據(jù)的測試:

????????測試正確的用戶名和密碼登錄成功

????????測試正確的用戶名和錯(cuò)誤的密碼登錄失敗

????????測試錯(cuò)誤的用戶名和正確的密碼登錄失敗

????????測試錯(cuò)誤的用戶名和密碼登錄失敗

????????在參數(shù)化中我們可以單參數(shù)、多參數(shù)、函數(shù)數(shù)據(jù)參數(shù)化

????????不管哪一種場景,它們都是數(shù)據(jù)不一樣而產(chǎn)生的問題。核心步驟其實(shí)都是一樣的---發(fā)送請求

? ? ? ? 我們采取的思想就是進(jìn)行數(shù)據(jù)分離--DDT數(shù)據(jù)驅(qū)動(dòng)

????????

# 1. 第一個(gè)情況:單數(shù)據(jù)
data = [值1,值2,值3...]
data = (值1,值2,值3...)單數(shù)據(jù),通過對應(yīng)的下標(biāo)去進(jìn)行獲取【pytest會(huì)自己進(jìn)行處理】# 2. 第一個(gè)情況:多數(shù)據(jù),列表和元組嵌套
data = [("admin","123456"),("admin","123456"),("admin","123456"),...]
data = (["admin","123456"],["admin","123456"],...)
多數(shù)據(jù),通過對應(yīng)的下標(biāo)去進(jìn)行獲取# 3.【重要】:列表嵌套字典
data = [{“name”:"admin","password":"123456"},
{“name”:"admin","password":"123456"},
{“name”:"admin","password":"123456"}
...]
多數(shù)據(jù),通過對應(yīng)的KEY去進(jìn)行獲取2. 引用對應(yīng)的數(shù)據(jù)
在對應(yīng)的方法上去加上一個(gè)裝飾器即可引用:
@pytest.mark.parametrize(argnames,argvalues)
@pytest.mark.parametrize("變量名",引用的變量的值)  #  引用上面的數(shù)據(jù),并且取名加:變量名

? ? ? ?2. Pytest+Excel接口自動(dòng)化框架

? ? ? ? 我們?nèi)绾螌?yīng)的數(shù)據(jù)信息進(jìn)行提取出來,我們?nèi)绾问褂胮ython來讀取Excel

讀取excel的方法如下

????????


import openpyxl
from collectionsFramework.P02_pytest_excel_allure.config import *class FileReader:"""專門用來讀取和寫入yaml、excel文件"""# 讀取excel--openpyxl -- 文件格式:.xlsx@staticmethod  # 直接通過類名進(jìn)行調(diào)用def read_excel(file_path=CASEDATAURL, sheet_name=SHEETNAME):"""讀取Excel文件,只支持 .xlsx文件:param file_path: 文件路徑:return: excel文件數(shù)據(jù),元組的格式"""# 打開現(xiàn)有的Excel文件或創(chuàng)建新的文件try:#  正常情況下直接打開workbook = openpyxl.load_workbook(file_path)except FileNotFoundError:workbook = openpyxl.Workbook()# 選擇或創(chuàng)建指定的工作表if sheet_name in workbook.sheetnames:# 【正常】  判斷有沒有對應(yīng)的shtttname ,有的話把對應(yīng)的數(shù)據(jù)給我加載出來worksheet = workbook[sheet_name]else:# 沒有的話,給我新建一個(gè)worksheet = workbook.create_sheet(sheet_name)# 獲取列名 --- 把第2行的數(shù)據(jù)拿出來作為我們的key值headers = [cell.value for cell in worksheet[2]]# print("所有的key", headers)# 將數(shù)據(jù)存儲為字典,并且放在我們data當(dāng)中data = []  # 所有的數(shù)據(jù)# 把小的數(shù)據(jù)從第三行開始for row in worksheet.iter_rows(min_row=3, values_only=True):data.append(dict(zip(headers, row)))# data.append(dict(zip(headers, row)))# data.append()# dict(zip(headers, row))  # key 和 value 一一對應(yīng)起來 ==={}workbook.close()# 所有的數(shù)據(jù)return dataif __name__ == '__main__':CaseData = FileReader.read_excel()print(CaseData)

EXCEL讀取的方法封裝

????????

????????

# -*- coding: utf-8 -*-
# @Time : 2023/11/8 20:55
# @Author : Hami
import json
import pytest
from collectionsFramework.P02_pytest_excel_allure.common.FileDataDriver import FileReader
from collectionsFramework.P02_pytest_excel_allure.api_keyword.api_key import ApiKeyclass TestCase:# 獲取對應(yīng)的數(shù)據(jù) CaseData 需要從文檔當(dāng)中去進(jìn)行讀取CaseData = FileReader.read_excel()ak = ApiKey()@pytest.mark.parametrize("CaseData", CaseData)def testCase(self, CaseData):# 沒一個(gè)對應(yīng)的數(shù)據(jù)都來臨,獲取對應(yīng)的接口請求的四要素# 1. 獲取數(shù)據(jù)(四要素) 2. 發(fā)送請求 3.獲取響應(yīng)數(shù)據(jù) 4.斷言# 1. 字典獲取的方式依次拿到# url = CaseData["url"]+CaseData["path"]# params = eval(CaseData["params"])# headers = eval(CaseData["headers"])# data = eval(CaseData["data"])dict_data = {"url":CaseData["url"]+CaseData["path"],"params": eval(CaseData["params"]),"headers": eval(CaseData["headers"]),"data": eval(CaseData["data"])}if CaseData["type"] == "json":dict_data["data"] = json.dumps(dict_data["data"])# self.ak.post(url=url,....)  # 不建議res = self.ak.post(**dict_data) # 不定長參數(shù)傳值方式print(res)

eval

eval() 函數(shù)是 Python 內(nèi)置的一個(gè)函數(shù),用于將字符串作為代碼執(zhí)行,并返回結(jié)果。
?

def add(a, b):
return a + b
result = eval("add(2, 3)")
print(result) # 輸出: 5

getattr()函數(shù)的應(yīng)用

????????getattr() 函數(shù)是 Python 內(nèi)置的一個(gè)函數(shù),用于獲取對象的屬性或方法

? ? getattr(object, name, default)
?object : 表示要獲取屬性或方法的對象。

name : 表示要獲取的屬性或方法的名稱。

default (可選): 表示當(dāng)屬性或方法不存在時(shí)的默認(rèn)值

例子如下

????????

"""
`getattr()` 函數(shù)是 Python 內(nèi)置的一個(gè)函數(shù),用于獲取對象的屬性或方法。
語法結(jié)構(gòu):
getattr(object, name, default)
- `object`: 表示要獲取屬性或方法的對象。
- `name`: 表示要獲取的屬性或方法的名稱。
- `default` (可選): 表示當(dāng)屬性或方法不存在時(shí)的默認(rèn)值。
"""
# 案例一:類當(dāng)中只有屬性
class MyClass:
name = "hami"
age = 18
obj = MyClass()
value = getattr(obj, "name")
print(value) # 輸出: hami
# 案例二:類當(dāng)中對應(yīng)的屬性不存在(有參數(shù)),如果直接參數(shù)不存在也沒有給參數(shù),報(bào)錯(cuò)
class MyClass:
name = "hami"
age = 18
obj = MyClass()
value = getattr(obj, "sex", "女")
print(value) # 輸出: hami
# 案例三:類當(dāng)中對應(yīng)的方法,一定要記得調(diào)用(無參數(shù))
class MyClass:
def greet(self):
print("Hello, world!")
obj = MyClass()
method = getattr(obj, "greet") # 返回對應(yīng)的方法
method() # 輸出: Hello, world!
# 案例四:類當(dāng)中對應(yīng)的方法,一定要記得調(diào)用(有參數(shù))
class MyClass:
def greet(self,name,age):
print("您的姓名是: {},年齡是:{}".format(name,age))
obj = MyClass()
method = getattr(obj, "greet")("hami","25") # 您的姓名是hami,年齡是:25

封裝主函數(shù)

????????


import json
import pytest
from collectionsFramework.P02_pytest_excel_allure.common.FileDataDriver import FileReader
from collectionsFramework.P02_pytest_excel_allure.api_keyword.api_key import ApiKey
from collectionsFramework.P02_pytest_excel_allure.config import *class TestCase:# 獲取對應(yīng)的數(shù)據(jù) CaseData 需要從文檔當(dāng)中去進(jìn)行讀取# 1. 獲取數(shù)據(jù)(四要素) 2. 發(fā)送請求 3.獲取響應(yīng)數(shù)據(jù) 4.斷言CaseData = FileReader.read_excel()ak = ApiKey()@pytest.mark.parametrize("CaseData", CaseData)def testCase(self, CaseData):# -------------------------發(fā)送請求-------------------------------try:# 請求數(shù)據(jù)dict_data = {"url": CaseData["url"] + CaseData["path"],"params": eval(CaseData["params"]),"headers": eval(CaseData["headers"]),"data": eval(CaseData["data"])}if CaseData["type"] == "json":dict_data["data"] = json.dumps(dict_data["data"])except Exception:value = MSG_DATA_ERROR# ----待定----print("寫入測試結(jié)果", value)else:# 得到對應(yīng)的響應(yīng)數(shù)據(jù)res = getattr(self.ak, CaseData["method"])(**dict_data)# -------------------------進(jìn)行斷言處理-------------------------------# 實(shí)際結(jié)果try:msg = self.ak.get_text(res.json(),CaseData["actualResult"])except Exception:value = MSG_EXDATA_ERROR# ----待定----print("寫入測試結(jié)果", value)else:# 只會(huì)是一個(gè)分支語言,但是不會(huì)造成測試結(jié)果成功或者失敗,所以必須無論如何都是需要斷言if msg == CaseData["expectResult"]:value = MSG_ASSERT_OKelse:value = MSG_ASSERT_NO# ----待定----print("寫入測試結(jié)果", value)finally:assert msg == CaseData["expectResult"],value

Allure報(bào)告日志及動(dòng)態(tài)標(biāo)題

????????


import json
import pytest
from collectionsFramework.P02_pytest_excel_allure.common.FileDataDriver import FileReader
from collectionsFramework.P02_pytest_excel_allure.api_keyword.api_key import ApiKey
from collectionsFramework.P02_pytest_excel_allure.config import *import allureclass TestCase:# 獲取對應(yīng)的數(shù)據(jù) CaseData 需要從文檔當(dāng)中去進(jìn)行讀取# 1. 獲取數(shù)據(jù)(四要素) 2. 發(fā)送請求 3.獲取響應(yīng)數(shù)據(jù) 4.斷言CaseData = FileReader.read_excel()ak = ApiKey()def __dynamic_title(self, CaseData):# # 動(dòng)態(tài)生成標(biāo)題# allure.dynamic.title(data[11])# 如果存在自定義標(biāo)題if CaseData["caseName"] is not None:# 動(dòng)態(tài)生成標(biāo)題allure.dynamic.title(CaseData["caseName"])if CaseData["storyName"] is not None:# 動(dòng)態(tài)獲取story模塊名allure.dynamic.story(CaseData["storyName"])if CaseData["featureName"] is not None:# 動(dòng)態(tài)獲取feature模塊名allure.dynamic.feature(CaseData["featureName"])if CaseData["remark"] is not None:# 動(dòng)態(tài)獲取備注信息allure.dynamic.description(CaseData["remark"])if CaseData["rank"] is not None:# 動(dòng)態(tài)獲取級別信息(blocker、critical、normal、minor、trivial)allure.dynamic.severity(CaseData["rank"])@pytest.mark.parametrize("CaseData", CaseData)def testCase(self, CaseData):self.__dynamic_title(CaseData)# -------------------------發(fā)送請求-------------------------------try:# 請求數(shù)據(jù)dict_data = {"url": CaseData["url"] + CaseData["path"],"params": eval(CaseData["params"]),"headers": eval(CaseData["headers"]),"data": eval(CaseData["data"])}if CaseData["type"] == "json":dict_data["data"] = json.dumps(dict_data["data"])except Exception:value = MSG_DATA_ERROR# ----待定----print("寫入測試結(jié)果", value)else:# 得到對應(yīng)的響應(yīng)數(shù)據(jù)res = getattr(self.ak, CaseData["method"])(**dict_data)# -------------------------進(jìn)行斷言處理-------------------------------# 實(shí)際結(jié)果try:msg = self.ak.get_text(res.json(),CaseData["actualResult"])except Exception:value = MSG_EXDATA_ERROR# ----待定----print("寫入測試結(jié)果", value)else:# 只會(huì)是一個(gè)分支語言,但是不會(huì)造成測試結(jié)果成功或者失敗,所以必須無論如何都是需要斷言if msg == CaseData["expectResult"]:value = MSG_ASSERT_OKelse:value = MSG_ASSERT_NO# ----待定----print("寫入測試結(jié)果", value)finally:assert msg == CaseData["expectResult"],value

3.Excel框架優(yōu)化及Yaml入門

? ? ? ? ?1.寫入excel框架

? ? ? ? ? ? ? ? ? ? ? ? 我們在FileDataDriver.py, 增加一個(gè)寫入excel的方法
????????????????????????

 @staticmethoddef writeDataToExcel(file_path=CASEDATAURL, sheet_name=SHEETNAME, row=None, column=None, value=None):# 打開現(xiàn)有的Excel文件或創(chuàng)建新的文件try:workbook = openpyxl.load_workbook(file_path)except FileNotFoundError:workbook = openpyxl.Workbook()# 選擇或創(chuàng)建指定的工作表if sheet_name in workbook.sheetnames:worksheet = workbook[sheet_name]else:worksheet = workbook.create_sheet(sheet_name)# 寫入數(shù)據(jù)到指定行和列worksheet.cell(row=row, column=column).value = value# 保存修改后的文件--- 所以執(zhí)行過程當(dāng)中excel是要關(guān)閉的狀態(tài)workbook.save(file_path)

? ? ? ? 在config.py中寫入對應(yīng)的常量,我們就可以在對應(yīng)的測試用例中修改代碼如下

????????


import json
import pytest
from YamlOptimization.P02_pytest_excel_allure.common.FileDataDriver import FileReader
from YamlOptimization.P02_pytest_excel_allure.api_keyword.api_key import ApiKey
from YamlOptimization.P02_pytest_excel_allure.config import *
import allureclass TestCase:# 獲取對應(yīng)的數(shù)據(jù) CaseData 需要從文檔當(dāng)中去進(jìn)行讀取# 1. 獲取數(shù)據(jù)(四要素) 2. 發(fā)送請求 3.獲取響應(yīng)數(shù)據(jù) 4.斷言AllCaseData = FileReader.read_excel()ak = ApiKey()def __dynamic_title(self, CaseData):# # 動(dòng)態(tài)生成標(biāo)題# allure.dynamic.title(data[11])# 如果存在自定義標(biāo)題if CaseData["caseName"] is not None:# 動(dòng)態(tài)生成標(biāo)題allure.dynamic.title(CaseData["caseName"])if CaseData["storyName"] is not None:# 動(dòng)態(tài)獲取story模塊名allure.dynamic.story(CaseData["storyName"])if CaseData["featureName"] is not None:# 動(dòng)態(tài)獲取feature模塊名allure.dynamic.feature(CaseData["featureName"])if CaseData["remark"] is not None:# 動(dòng)態(tài)獲取備注信息allure.dynamic.description(CaseData["remark"])if CaseData["rank"] is not None:# 動(dòng)態(tài)獲取級別信息(blocker、critical、normal、minor、trivial)allure.dynamic.severity(CaseData["rank"])@pytest.mark.parametrize("CaseData", AllCaseData)def testCase(self, CaseData):self.__dynamic_title(CaseData)# 寫Excle的行和列row = CaseData["id"]column = 11# 初始化對應(yīng)的值:res = Nonemsg = Nonevalue = None# -------------------------發(fā)送請求-------------------------------try:# 請求數(shù)據(jù)dict_data = {"url": CaseData["url"] + CaseData["path"],"params": eval(CaseData["params"]),"headers": eval(CaseData["headers"]),"data": eval(CaseData["data"])}if CaseData["type"] == "json":dict_data["data"] = json.dumps(dict_data["data"])except Exception:value = MSG_DATA_ERRORFileReader.writeDataToExcel(row=row,column=column,value=value)else:# 得到對應(yīng)的響應(yīng)數(shù)據(jù)res = getattr(self.ak, CaseData["method"])(**dict_data)# -------------------------進(jìn)行斷言處理-------------------------------# 實(shí)際結(jié)果try:msg = self.ak.get_text(res.json(), CaseData["actualResult"])except Exception:value = MSG_EXDATA_ERRORFileReader.writeDataToExcel(row=row,column=column,value=value)else:# 只會(huì)是一個(gè)分支語言,但是不會(huì)造成測試結(jié)果成功或者失敗,所以必須無論如何都是需要斷言if msg == CaseData["expectResult"]:value = MSG_ASSERT_OKelse:value = MSG_ASSERT_NOFileReader.writeDataToExcel(row=row,column=column,value=value)finally:assert msg == CaseData["expectResult"], value

? ?? ? ?2.實(shí)現(xiàn)優(yōu)化接口關(guān)聯(lián)

? ? ? ? 思路:

  1. excel ---字段 {"key":"value"} ----{"變量名":"jsonpath值","變量名":"jsonpath值"}

{"token":"$..token","name":"$..name"}

? ? 2. 寫一個(gè)方法:

循環(huán)遍歷這個(gè)值 :{"token":"$..token","name":"$..name"}

遍歷的過程當(dāng)中,通過"$..token"提取具體的值:56465456456313521456 ---new_value

3. 定義一個(gè)全局變量:專門用來存放提取之后的數(shù)據(jù)。

all_val={"token":"56465456456313521456","name":"hami"}

代碼如下:

????????

  def __json_extraction(self, CaseData, res):"""提取響應(yīng)之后的數(shù)據(jù):param CaseData: 當(dāng)前的Case,主要獲取需要提取數(shù)據(jù)的字段:jsonExData:param res:響應(yīng)得到的對應(yīng)的結(jié)果:return:"""try:if CaseData["jsonExData"]:Exdata = eval(CaseData["jsonExData"])  # {"VAR_TOKEN":"$..token","MSG":"$.msg"}print("需要提取的數(shù)據(jù):>>>", Exdata)for key, value in Exdata.items():# 通過對應(yīng)的jsonpath獲取具體的數(shù)據(jù)new_value = self.ak.get_text(res.json(), value)self.all_var.update({key: new_value})print("提取出來的數(shù)據(jù):>>>", self.all_var)else:print("需要提取的數(shù)據(jù)為空")except Exception:print("請檢查你需要提取數(shù)據(jù)數(shù)據(jù)格式的正確性。")

3.進(jìn)行變量渲染

? ? ? ? 我們提取出來的casedata如下所示

????????

我們可以看到此處的id和var_token沒有具體的值,我們需要把具體的值渲染進(jìn)去

????????

 all_val = {"VAR_TOKEN": "134324324324", "id": "158"}CaseData = {"id": 3,"url": "http://novel.hctestedu.com/book/queryBookDetail/{{id}}",'params': '{"application": "app",\n"application_client_type": "weixin",\n"token":  "{{VAR_TOKEN}}"}'}CaseData = eval(Template(str(CaseData)).render(all_val))

就用template來進(jìn)行渲染

3.數(shù)據(jù)庫操作(提取數(shù)據(jù))

? ? ? ? 我們的思路如下:

  1. 框架能夠連接數(shù)據(jù)庫
  2. 執(zhí)行SQL
  3. 把數(shù)據(jù)返回

思路:同json提取器

從數(shù)據(jù)庫提取數(shù)據(jù):Excle進(jìn)行維護(hù) ;思路:同json提取器

? ?1.游標(biāo)對象

????????在數(shù)據(jù)庫中,游標(biāo)是一個(gè)十分重要的概念。游標(biāo)提供了一種從表中檢索出的數(shù)據(jù)進(jìn)行操作的靈活手段,就本質(zhì)而言,游標(biāo)實(shí)際上是一種能從包括多條數(shù)據(jù)記錄的結(jié)果集中每次提取一條記錄的機(jī)制。游標(biāo)總是與一條SQL 選擇語句相關(guān)聯(lián)因?yàn)橛螛?biāo)由結(jié)果集(可以是零條,一條或由相關(guān)的選擇語句檢索出的多條記錄)和結(jié)果集中指向特定記錄的游標(biāo)位置組成。當(dāng)決定對結(jié)果進(jìn)行處理時(shí),必須聲明一個(gè)指向該結(jié)果的游標(biāo)
????????

? ? ? ? 常用的方法:

????????cursor(): 創(chuàng)建游標(biāo)對象

????????close(): 關(guān)閉游標(biāo)對象

????????fetchone(): 得到結(jié)果集的下一行

????????fetchmany([size = cursor.arraysize]):得到結(jié)果集的下幾行fetchall():得到結(jié)果集中剩下的所有行

????????excute(sql[,args]): 執(zhí)行一個(gè)數(shù)據(jù)庫查詢或命令executemany(sql,args):執(zhí)行多個(gè)數(shù)據(jù)庫查詢或命令

? ? ? 例子如下:

????????

"""
在測試過程中偶然需要從數(shù)據(jù)庫獲取數(shù)據(jù)進(jìn)行測試或者通過數(shù)據(jù)庫的數(shù)據(jù)進(jìn)行斷言,這時(shí)候既要連接到數(shù)據(jù)庫。python當(dāng)中利用PySQL進(jìn)行連接
安裝:pip install pymysql
"""
import pymysql# 1. 配置數(shù)據(jù)庫連接信息并連接
connection = pymysql.connect(host='shop-xo.hctestedu.com',  # 數(shù)據(jù)庫地址port=3306,user='api_test',  # 數(shù)據(jù)庫用戶名password='Aa9999!',  # 數(shù)據(jù)庫密碼db='shopxo_hctested',  # 數(shù)據(jù)庫名稱
)# 2. 創(chuàng)建游標(biāo)對象,使用它進(jìn)行操作---人
cursor = connection.cursor()# 3. SQL語句---飯
sql =  "SELECT username FROM sxo_user WHERE id = 75;"# 4. 使用游標(biāo)對象去執(zhí)行操作SQL
cursor.execute(sql)# 5. 得到結(jié)果集的下一行
result = cursor.fetchone()print(result)  # 元組
# 6. 關(guān)閉數(shù)據(jù)庫連接
cursor.close()

2.我們繼續(xù)優(yōu)化代碼?將數(shù)據(jù)庫提取的操作寫入api_key和測試用例當(dāng)中

? ? ? ? api中

 @allure.step(">>>>>>:開始提取數(shù)據(jù)庫的數(shù)據(jù)")def get_sqlData(self, sqlValue):""":param sqlValue: SQL,返回的數(shù)據(jù)是一個(gè)元組:return:"""import pymysql# 1. 配置數(shù)據(jù)庫連接信息并連接connection = pymysql.connect(host=DB_HOST,  # 數(shù)據(jù)庫地址port=DB_PORT,user=DB_USER,  # 數(shù)據(jù)庫用戶名password=DB_PASSWORD,  # 數(shù)據(jù)庫密碼db=DB_NAME,  # 數(shù)據(jù)庫名稱)# 2. 創(chuàng)建游標(biāo)對象,使用它進(jìn)行操作cursor = connection.cursor()# 4. 使用游標(biāo)對象去執(zhí)行操作SQLcursor.execute(sqlValue)# 5. 得到結(jié)果集的下一行result = cursor.fetchone()# 6. 關(guān)閉數(shù)據(jù)庫連接cursor.close()return result[0]

測試用例中

????????

    def __sql_extraction(self,CaseData):"""從數(shù)據(jù)庫提取數(shù)據(jù):param CaseData: 當(dāng)前的Case,主要獲取需要提取數(shù)據(jù)的字段:sqlExData:return:"""try:if CaseData["sqlExData"]:Exdata = eval(CaseData["sqlExData"])  # {"name":"SELECT username FROM sxo_user WHERE username='hami'","id":"SELECT id FROM sxo_user WHERE username='hami'"}print("SQL-需要提取的數(shù)據(jù):>>>", Exdata)for key, value in Exdata.items():# 通過對應(yīng)的sql獲取具體的數(shù)據(jù)new_value = self.ak.get_sqlData(value)self.all_var.update({key: new_value})print("SQL-提取出來的數(shù)據(jù):>>>", self.all_var)else:print("SQL-需要提取的數(shù)據(jù)為空")except Exception:print("SQL-請檢查你需要提取數(shù)據(jù)數(shù)據(jù)格式的正確性。")

4.數(shù)據(jù)庫操作-數(shù)據(jù)庫斷言【一般是極為重要的接口我們?nèi)プ觥?/h3>
  1. 檢查數(shù)據(jù)庫是否有這個(gè)用戶? --- 數(shù)據(jù)庫斷言
  2. 是否能夠正確的登錄

????????

思路:excel

  1. 期望結(jié)果:{"username":"yeye"}
  2. 實(shí)際結(jié)果:{"username":"SELECT username FROM sxo_user WHERE id=75"}

? ? ? ? 代碼如下

????????

  def __sql_assertData(self, CaseData):res = Trueif CaseData["sqlAssertData"] and CaseData["sqlExpectRe ult"]:# 實(shí)際結(jié)果:從數(shù)據(jù)庫讀取出來的數(shù)據(jù)--字典的格式 # {"name":"SELECT username FROM sxo_user WHERE username='hami'","id":"SELECT id FROM sxo_user WHERE username='hami'"}realityData = eval(CaseData["sqlAssertData"])# 期望結(jié)果:{"name":"hami","id":75}expectData = json.loads(CaseData["sqlExpectResult"])realityDataDict = {}for key, value in realityData.items():# 通過對應(yīng)的sql獲取具體的數(shù)據(jù)new_value = self.ak.get_sqlData(value)realityDataDict.update({key: new_value})if expectData != realityDataDict:res = Falsereturn res

整個(gè)側(cè)事故用例代碼如下

????????

# -*- coding: utf-8 -*-
# @Time : 2023/11/8 20:55
# @Author : Hami
import json
import pytest
from YamlOptimization.P02_pytest_excel_allure.common.FileDataDriver import FileReader
from YamlOptimization.P02_pytest_excel_allure.api_keyword.api_key import ApiKey
from YamlOptimization.P02_pytest_excel_allure.config import *
import allure
from jinja2 import Template  # 變量渲染class TestCase:# 獲取對應(yīng)的數(shù)據(jù) CaseData 需要從文檔當(dāng)中去進(jìn)行讀取# 1. 獲取數(shù)據(jù)(四要素) 2. 發(fā)送請求 3.獲取響應(yīng)數(shù)據(jù) 4.斷言AllCaseData = FileReader.read_excel()ak = ApiKey()# 定義:all_val 存放提取出的數(shù)據(jù)all_var = {}def __dynamic_title(self, CaseData):# # 動(dòng)態(tài)生成標(biāo)題# allure.dynamic.title(data[11])# 如果存在自定義標(biāo)題if CaseData["caseName"] is not None:# 動(dòng)態(tài)生成標(biāo)題allure.dynamic.title(CaseData["caseName"])if CaseData["storyName"] is not None:# 動(dòng)態(tài)獲取story模塊名allure.dynamic.story(CaseData["storyName"])if CaseData["featureName"] is not None:# 動(dòng)態(tài)獲取feature模塊名allure.dynamic.feature(CaseData["featureName"])if CaseData["remark"] is not None:# 動(dòng)態(tài)獲取備注信息allure.dynamic.description(CaseData["remark"])if CaseData["rank"] is not None:# 動(dòng)態(tài)獲取級別信息(blocker、critical、normal、minor、trivial)allure.dynamic.severity(CaseData["rank"])def __json_extraction(self, CaseData, res):"""提取響應(yīng)之后的數(shù)據(jù):param CaseData: 當(dāng)前的Case,主要獲取需要提取數(shù)據(jù)的字段:jsonExData:param res:響應(yīng)得到的對應(yīng)的結(jié)果:return:"""try:if CaseData["jsonExData"]:Exdata = eval(CaseData["jsonExData"])  # {"VAR_TOKEN":"$..token","MSG":"$.msg"}print("需要提取的數(shù)據(jù):>>>", Exdata)for key, value in Exdata.items():# 通過對應(yīng)的jsonpath獲取具體的數(shù)據(jù)new_value = self.ak.get_text(res.json(), value)self.all_var.update({key: new_value})print("提取出來的數(shù)據(jù):>>>", self.all_var)else:print("需要提取的數(shù)據(jù)為空")except Exception:print("請檢查你需要提取數(shù)據(jù)數(shù)據(jù)格式的正確性。")def __sql_extraction(self, CaseData):"""從數(shù)據(jù)庫提取數(shù)據(jù):param CaseData: 當(dāng)前的Case,主要獲取需要提取數(shù)據(jù)的字段:sqlExData:return:"""try:if CaseData["sqlExData"]:Exdata = eval(CaseData["sqlExData"])  # {"name":"SELECT username FROM sxo_user WHERE username='hami'","id":"SELECT id FROM sxo_user WHERE username='hami'"}print("SQL-需要提取的數(shù)據(jù):>>>", Exdata)for key, value in Exdata.items():# 通過對應(yīng)的sql獲取具體的數(shù)據(jù)new_value = self.ak.get_sqlData(value)self.all_var.update({key: new_value})print("SQL-提取出來的數(shù)據(jù):>>>", self.all_var)else:print("SQL-需要提取的數(shù)據(jù)為空")except Exception:print("SQL-請檢查你需要提取數(shù)據(jù)數(shù)據(jù)格式的正確性。")def __sql_assertData(self, CaseData):res = Trueif CaseData["sqlAssertData"] and CaseData["sqlExpectRe ult"]:# 實(shí)際結(jié)果:從數(shù)據(jù)庫讀取出來的數(shù)據(jù)--字典的格式 # {"name":"SELECT username FROM sxo_user WHERE username='hami'","id":"SELECT id FROM sxo_user WHERE username='hami'"}realityData = eval(CaseData["sqlAssertData"])# 期望結(jié)果:{"name":"hami","id":75}expectData = json.loads(CaseData["sqlExpectResult"])realityDataDict = {}for key, value in realityData.items():# 通過對應(yīng)的sql獲取具體的數(shù)據(jù)new_value = self.ak.get_sqlData(value)realityDataDict.update({key: new_value})if expectData != realityDataDict:res = Falsereturn res@pytest.mark.parametrize("CaseData", AllCaseData)def testCase(self, CaseData):self.__dynamic_title(CaseData)CaseData = eval(Template(str(CaseData)).render(self.all_var))print(CaseData)# 寫Excle的行和列row = CaseData["id"]column = 11# 初始化對應(yīng)的值:res = Nonemsg = Nonevalue = None# -------------------------發(fā)送請求-------------------------------try:# 請求數(shù)據(jù)dict_data = {"url": CaseData["url"] + CaseData["path"],"params": eval(CaseData["params"]),"headers": eval(CaseData["headers"]),"data": eval(CaseData["data"])}if CaseData["type"] == "json":dict_data["data"] = json.dumps(dict_data["data"])except Exception:value = MSG_DATA_ERRORFileReader.writeDataToExcel(row=row, column=column, value=value)else:# 得到對應(yīng)的響應(yīng)數(shù)據(jù)res = getattr(self.ak, CaseData["method"])(**dict_data)# -------------------------提取數(shù)據(jù)庫的操作---------------------------self.__sql_extraction(CaseData)# -------------------------進(jìn)行斷言處理-------------------------------# 實(shí)際結(jié)果try:msg = self.ak.get_text(res.json(), CaseData["actualResult"])except Exception:value = MSG_EXDATA_ERRORFileReader.writeDataToExcel(row=row, column=column, value=value)else:# 只會(huì)是一個(gè)分支語言,但是不會(huì)造成測試結(jié)果成功或者失敗,所以必須無論如何都是需要斷言if msg == CaseData["expectResult"]:value = MSG_ASSERT_OK# 成功之后進(jìn)行數(shù)據(jù)提取self.__json_extraction(CaseData, res)else:value = MSG_ASSERT_NOFileReader.writeDataToExcel(row=row, column=column, value=value)finally:assert msg == CaseData["expectResult"], value# -------------------------進(jìn)行數(shù)據(jù)庫斷言處理-------------------------------try:res = self.__sql_assertData(CaseData)  # False Trueexcept:print("SQL斷言出現(xiàn)問題")value = "SQL斷言出現(xiàn)問題"assert res, valueelse:assert resfinally:FileReader.writeDataToExcel(row=row, column=column, value=value)

5.yaml應(yīng)用?

? ? ? ? ? ? ? ? yaml的概念:

????????????????YAML 的語法和其他高級語言類似,并且可以簡單表達(dá)清單、散列表,標(biāo)量等數(shù)據(jù)形態(tài)。它使用空白符號縮進(jìn)和大量依賴外觀的特色,特別適合用來表達(dá)或編輯數(shù)據(jù)結(jié)構(gòu)、各種配置文件、傾印調(diào)試內(nèi)容、文件大綱(例如:許多電子郵件標(biāo)題格式和YAML非常接近)


????????YAML 的配置文件后綴為 .yml或.yaml,如:huace.yml

? ? ? ? 基本語法:

????????大小寫敏感

????????使用縮進(jìn)表示層級關(guān)系

????????縮進(jìn)不允許使用tab,只允許空格

????????縮進(jìn)的空格數(shù)不重要,只要相同層級的元素左對齊即可

????????'#' 表示注釋

? ? ? ? Yaml當(dāng)中如果是數(shù)字字符的話,一定要加雙引號(不加就是一個(gè)整型)

? ? ? ? 數(shù)據(jù)類型

純量:字符串/數(shù)字 ,直接寫就好了

列表:用符號去代替: -

字典:key : value

符號后面必須要有對應(yīng)空格

? ? ? ? ? ? ? ? 我們的yaml中可以這樣寫

????????????????

data:
-id: "0001"name: "qsdd"
-id: "0002"name: "yeyeyeye"

可以成功轉(zhuǎn)換為json格式

?也可以這樣寫:

data: [{ "id": "0001"},{ "id": "0002"}]

? ? ? ? 也可以轉(zhuǎn)換為json格式

? ? ? ? excel格式的轉(zhuǎn)換

????????

方法一:
- {"id":"0001","name":"hami"}
-{"id":"0002","name":"hami"}
方法二:
- id: "0001"name: hami1
-id: 0002name: hami2效果:[{"id":"0001","name":"hami"},{"id":"0002","name":"hami"}]

excel轉(zhuǎn)換為yaml格式

? ? ? ? ? ? ? ? 代碼如下

????????


"""
YAML 是 "YAML Ain't a Markup Language" -- 數(shù)據(jù)格式
YAML 的配置文件后綴為 .yml或.yam,如:huace.yml 。1.1 基本語法
- 大小寫敏感
- 使用縮進(jìn)表示層級關(guān)系
- 縮進(jìn)不允許使用tab,只允許空格
- 縮進(jìn)的空格數(shù)不重要,只要相同層級的元素左對齊即可
- '#' 表示注釋YAML 支持以下幾種數(shù)據(jù)類型:
- 對象:鍵值對的集合,又稱為映射(mapping)/ 哈希(hashes) / 字典(dictionary)
- 數(shù)組:一組按次序排列的值,又稱為序列(sequence) / 列表(list)
- 純量(scalars):單個(gè)的、不可再分的值 -- 任意的數(shù)據(jù)類型對象格式: key: value
數(shù)組格式: -可以在在線網(wǎng)址先確定格式的正確性:https://tool.p2hp.com/tool-format-yaml/安裝:pip install pyyaml
"""
# 1. 讀取數(shù)據(jù)
import yaml# file_path = "yamlData/test_yaml_04.yaml"
file_path = "yamlData/x_testFavor.yaml"
with open(file_path, 'r', encoding="utf-8") as file:data = yaml.safe_load(file)
print(data)# # 2. 修改數(shù)據(jù)
# data[1]["res"] = "執(zhí)行失敗"
#
# # 3. 寫入數(shù)據(jù)
# with open(file_path, 'w', encoding="utf-8") as file:
#     # allow_unicode=True,避免將中文字符轉(zhuǎn)換為 Unicode 轉(zhuǎn)義序列
#     yaml.dump(data, file, allow_unicode=True)

對yaml進(jìn)行讀寫

我們在專門用來讀寫yaml和excel的py文件中新增一個(gè)方法

????????

  @staticmethoddef write_yaml(data, file_path=YAMLDATA):"""寫入yaml文件,寫入無序沒有關(guān)系,通過key獲取數(shù)據(jù):param data: 需要寫入的數(shù)據(jù):param file_path: 文件路徑:return:"""with open(file_path, 'w', encoding='utf-8') as file:# 可以結(jié)合異常處理進(jìn)行封裝try:yaml.dump(data, file, allow_unicode=True)print("YAML數(shù)據(jù)寫入成功。")except yaml.YAMLError as e:print(f"YAML數(shù)據(jù)寫入失敗: {e}")

對框架進(jìn)行修改

?我們改成讀取yaml文件

????????對應(yīng)的讀取讀取數(shù)據(jù)源的方法需要修改成: AllCaseData = FileReader.read_yaml()

????????寫入到Y(jié)aml文件,所以無需行號去進(jìn)行記錄,可刪除變量: row、cell


????????因?yàn)橥ㄟ^Yaml讀取出來的本身就是json,所以 dict_data 這個(gè)變量值,有可能

是字典,也有可能是字符串,所以為了靈活起見,統(tǒng)一改成如下,同時(shí)也可以直接去掉eval方法即可

????????

# 擴(kuò)展:不做強(qiáng)制要求
# 字符串
# input_string = "{'name':'Alice', 'age':'25', 'city':'New York'}"
# 字典
input_string = {'name':'Alice', 'age':'25', 'city':'New York'}print("轉(zhuǎn)之前:", type(input_string))  # 字符串
# 如果input_string類型是str 則 轉(zhuǎn)成字典eval(input_string); 否則的話:直接輸出 ( else input_string)
result = eval(input_string) if isinstance(input_string, str) else input_string
print("轉(zhuǎn)之后:", type(result))  # 字典
print(result)

就是判斷值是字典還是字符串?是字符串就轉(zhuǎn)為字典

我們只需要在測試用例中修改讀寫的數(shù)據(jù)

????????

再根據(jù)情況修改上述的轉(zhuǎn)換格式的代碼?即可

回寫數(shù)據(jù)到y(tǒng)aml

????????首先我們寫入的時(shí)候是寫入所有的數(shù)據(jù)到data 當(dāng)中

如,我們所有讀取出來的數(shù)據(jù)是AllCaseData,比如如下格式

????????

[{id":0,"caseName":"登錄接口","result":nall},
{id":1,"caseName":"加入購物車","result":nall}]

通過參數(shù)化方式我們每次能夠拿到一條數(shù)據(jù),比如你要修改第一個(gè)這條數(shù)據(jù),可以
?

CaseData["result"] = value

重點(diǎn):但是你修改的只是這一條數(shù)據(jù),直接寫入就會(huì)不正確(覆蓋其它的數(shù)據(jù))。
所以,正確的做法是:這里的CaseData["id"] 代表下標(biāo)。
?

AllCaseData[CaseData["id"] ] = value

yaml+allure+pytest框架如下所示:

????????


import json
import pytest
from YamlOptimization.pytest_yaml_allure.common.FileDataDriver import FileReader
from YamlOptimization.pytest_yaml_allure.api_keyword.api_key import ApiKey
from YamlOptimization.pytest_yaml_allure.config import *
import allure
from jinja2 import Template  # 變量渲染class TestCase:# 獲取對應(yīng)的數(shù)據(jù) CaseData 需要從文檔當(dāng)中去進(jìn)行讀取# 1. 獲取數(shù)據(jù)(四要素) 2. 發(fā)送請求 3.獲取響應(yīng)數(shù)據(jù) 4.斷言AllCaseData = FileReader.read_yaml()ak = ApiKey()# 定義:all_val 存放提取出的數(shù)據(jù)all_var = {}def __dynamic_title(self, CaseData):# # 動(dòng)態(tài)生成標(biāo)題# allure.dynamic.title(data[11])# 如果存在自定義標(biāo)題if CaseData["caseName"] is not None:# 動(dòng)態(tài)生成標(biāo)題allure.dynamic.title(CaseData["caseName"])if CaseData["storyName"] is not None:# 動(dòng)態(tài)獲取story模塊名allure.dynamic.story(CaseData["storyName"])if CaseData["featureName"] is not None:# 動(dòng)態(tài)獲取feature模塊名allure.dynamic.feature(CaseData["featureName"])if CaseData["remark"] is not None:# 動(dòng)態(tài)獲取備注信息allure.dynamic.description(CaseData["remark"])if CaseData["rank"] is not None:# 動(dòng)態(tài)獲取級別信息(blocker、critical、normal、minor、trivial)allure.dynamic.severity(CaseData["rank"])def __json_extraction(self, CaseData, res):"""提取響應(yīng)之后的數(shù)據(jù):param CaseData: 當(dāng)前的Case,主要獲取需要提取數(shù)據(jù)的字段:jsonExData:param res:響應(yīng)得到的對應(yīng)的結(jié)果:return:"""try:if CaseData["jsonExData"]:Exdata = CaseData["jsonExData"] # {"VAR_TOKEN":"$..token","MSG":"$.msg"}print("需要提取的數(shù)據(jù):>>>", Exdata)for key, value in Exdata.items():# 通過對應(yīng)的jsonpath獲取具體的數(shù)據(jù)new_value = self.ak.get_text(res.json(), value)self.all_var.update({key: new_value})print("提取出來的數(shù)據(jù):>>>", self.all_var)else:print("需要提取的數(shù)據(jù)為空")except Exception:print("請檢查你需要提取數(shù)據(jù)數(shù)據(jù)格式的正確性。")def __sql_extraction(self, CaseData):"""從數(shù)據(jù)庫提取數(shù)據(jù):param CaseData: 當(dāng)前的Case,主要獲取需要提取數(shù)據(jù)的字段:sqlExData:return:"""try:if CaseData["sqlExData"]:Exdata = CaseData["sqlExData"]  # {"name":"SELECT username FROM sxo_user WHERE username='hami'","id":"SELECT id FROM sxo_user WHERE username='hami'"}print("SQL-需要提取的數(shù)據(jù):>>>", Exdata)for key, value in Exdata.items():# 通過對應(yīng)的sql獲取具體的數(shù)據(jù)new_value = self.ak.get_sqlData(value)self.all_var.update({key: new_value})print("SQL-提取出來的數(shù)據(jù):>>>", self.all_var)else:print("SQL-需要提取的數(shù)據(jù)為空")except Exception:print("SQL-請檢查你需要提取數(shù)據(jù)數(shù)據(jù)格式的正確性。")def __sql_assertData(self, CaseData):res = Trueif CaseData["sqlAssertData"] and CaseData["sqlExpectResult"]:# 實(shí)際結(jié)果:從數(shù)據(jù)庫讀取出來的數(shù)據(jù)--字典的格式 # {"name":"SELECT username FROM sxo_user WHERE username='hami'","id":"SELECT id FROM sxo_user WHERE username='hami'"}realityData = CaseData["sqlAssertData"]# 期望結(jié)果:{"name":"hami","id":75}expectData = CaseData["sqlExpectResult"]realityDataDict = {}for key, value in realityData.items():# 通過對應(yīng)的sql獲取具體的數(shù)據(jù)new_value = self.ak.get_sqlData(value)realityDataDict.update({key: new_value})if expectData != realityDataDict:res = Falsereturn res@pytest.mark.parametrize("CaseData", AllCaseData)def testCase(self, CaseData):self.__dynamic_title(CaseData)CaseData = eval(Template(str(CaseData)).render(self.all_var))print(CaseData)# 寫Yaml的下標(biāo)row = CaseData["id"]# 初始化對應(yīng)的值:res = Nonemsg = Nonevalue = None# 知識:是否斷言# is_assert = True# -------------------------發(fā)送請求-------------------------------try:# 請求數(shù)據(jù)params = eval(CaseData["params"]) if isinstance(CaseData["params"], str) else CaseData["params"]dict_data = {"url": CaseData["url"] + CaseData["path"],"params": params,"headers": CaseData["headers"],"data": CaseData["data"]}if CaseData["type"] == "json":dict_data["data"] = json.dumps(dict_data["data"])except Exception:value = MSG_DATA_ERRORCaseData["result"] = valueelse:# 得到對應(yīng)的響應(yīng)數(shù)據(jù)res = getattr(self.ak, CaseData["method"])(**dict_data)# -------------------------提取數(shù)據(jù)庫的操作---------------------------self.__sql_extraction(CaseData)# -------------------------進(jìn)行斷言處理-------------------------------# 實(shí)際結(jié)果try:msg = self.ak.get_text(res.json(), CaseData["actualResult"])except Exception:value = MSG_EXDATA_ERRORCaseData["result"] = valueelse:# 只會(huì)是一個(gè)分支語言,但是不會(huì)造成測試結(jié)果成功或者失敗,所以必須無論如何都是需要斷言if msg == CaseData["expectResult"]:value = MSG_ASSERT_OK# 成功之后進(jìn)行數(shù)據(jù)提取self.__json_extraction(CaseData, res)else:# is_assert = Falsevalue = MSG_ASSERT_NOCaseData["result"] = valuefinally:assert msg == CaseData["expectResult"], value# -------------------------進(jìn)行數(shù)據(jù)庫斷言處理-------------------------------try:res = self.__sql_assertData(CaseData)  # False Trueexcept:print("SQL斷言出現(xiàn)問題")value = "SQL斷言出現(xiàn)問題"assert res, valueelse:assert resfinally:CaseData["result"] = value# -------------------------把當(dāng)前的CaseData值寫入:可以通過后置處理方法去處理-------------------------------self.AllCaseData[row] = CaseDataFileReader.write_yaml(self.AllCaseData)

4.大量響應(yīng)報(bào)文處理及加解密、簽名處理

? ? ? ? 1.全字段斷言-DeepDiff

????????deepdiff 是一個(gè)Python庫,用于比較Python數(shù)據(jù)結(jié)構(gòu)(例如字典、列表、JSON等)之間的差異。它不僅可以比較簡單的Python數(shù)據(jù)類型,還可以比較任意深度或復(fù)雜度的數(shù)據(jù)結(jié)構(gòu)。

在Python中,我們經(jīng)常需要比較兩個(gè)JSON對象的異同。例如測試中,我們需要比較預(yù)期輸出和實(shí)際輸出是否相同。而在開發(fā)中,我們也需要比較兩個(gè)JSON對象的差異以便維護(hù)。使用 deepdiff 庫,可以輕松處理這些場景

????????DeepDiff庫的主要模塊如下:
????????

????????1. deepdiff.DeepDiff :這是DeepDiff庫的核心模塊,提供了比較兩個(gè)對象之間差異的功能。它可以比較字典、列表、集合等復(fù)雜對象,并返回差異的詳細(xì)信息。

2. deepdiff.DeepSearch :這是一個(gè)工具類,用于在復(fù)雜對象中搜索指定值。它可以深度遍歷對象,并返回找到的匹配項(xiàng)的路徑信息。

3. deepdiff.DeepHash :這個(gè)模塊用于生成復(fù)雜對象的哈希值。它可以遞歸地計(jì)算對象的哈希值,并考慮對象中的差異

? 2.deepdiff常用操作

????????如果實(shí)際請求結(jié)果和預(yù)期值的json數(shù)據(jù)都一致,那么會(huì)返回 {} 空字典,否則會(huì)返回對比差異的結(jié)果,接口測試中我們也可以根據(jù)這個(gè)特點(diǎn)進(jìn)行斷言

????????如果對比結(jié)果不同,將會(huì)給出下面對應(yīng)的返回
????????1. type_changes:類型改變的key=

????????2. values_changed:值發(fā)生變化的key

????????3. dictionary_item_added:字典key添加

????????4. dictionary_item_removed:字段key刪除

? ? ? ? 案例如下

????????


from deepdiff import DeepDiff
"""
總結(jié):
1. 當(dāng)數(shù)據(jù)沒有差異的時(shí)候: 返回是一個(gè)空字典 {}
2. 當(dāng)數(shù)據(jù)有差異的情況,會(huì)根據(jù)實(shí)際情況顯示:1. type_changes:類型改變的key2. values_changed:值發(fā)生變化的key3. dictionary_item_added:字典key添加4. dictionary_item_removed:字段key刪除
"""# 期望結(jié)果
exjson = {'code': 0,"message": "成功","data": {"total": 28,"id": 123}
}# 實(shí)際結(jié)果
sjjson= {'code': 0,"message": "成功","data": {"total": 28,"id": 123}
}# 1. 如果兩個(gè)json 是一樣的情況下,返回的值是一個(gè)空字典
res = DeepDiff(exjson,sjjson)
print(res)實(shí)際結(jié)果
sjjson = {'code': "0",  # 類型不一樣"message": "成功","data": {"total": 28,"id": 123}
}# 2. 類型錯(cuò)誤會(huì)提示:{'type_changes':XXXXXXXXX},root代表的是根節(jié)點(diǎn)
res = DeepDiff(exjson, sjjson)
print(res)  # {'type_changes':XXXXXXXXX}
sjjson = {'code': 100,  # 類型一樣,數(shù)據(jù)不一樣"message": "成功","data": {"total": 28,"id": 123}
}
3. 當(dāng)你的值有改變,會(huì)顯示 :values_changed
res = DeepDiff(exjson, sjjson)
print(res)  # 'values_changed': {"root['code']": {'new_value': 100, 'old_value': 0}}}sjjson = {'code': 0,  # 類型一樣,數(shù)據(jù)不一樣"message": "成功","data": {"total": 28,"id": 123},"add": "長沙"
}
res = DeepDiff(exjson, sjjson)
print(res)  # {'dictionary_item_added': [root['add']]}sjjson = {"message": "成功","data": {"total": 28,"id": 123}
}
res = DeepDiff(exjson, sjjson)
print(res)  # {'dictionary_item_removed': [root['code']]}



忽略排序、大小寫及某個(gè)字段\

其實(shí),在實(shí)際接口斷言中,可能需要校驗(yàn)的字段順序不一樣,又或者有一些字段值不需要,為了解決這類問題,Deepdiff也提供了相信的參數(shù),只需要在比較的時(shí)候加入,傳入對應(yīng)參數(shù)即可

例如?我們遇到一個(gè)相應(yīng)數(shù)據(jù):

期望結(jié)果:

{"code":"200","ordeid":"OR567456415645646",data:"241523415361123132132"}

實(shí)際結(jié)果:【未定】--- ID 是不確定的,是后端自動(dòng)生成的,過濾字段。

{"code":"200","ordeid":"OR567456415645646",data:"241523415361123132132"}

ignore_order(忽略排序)

ignore_string_case(忽略大小寫)

exclude_paths排除指定的字段

from deepdiff import DeepDiff"""
總結(jié):
1. 當(dāng)數(shù)據(jù)沒有差異的時(shí)候: 返回是一個(gè)空字典 {}
2. 當(dāng)數(shù)據(jù)有差異的情況,會(huì)根據(jù)實(shí)際情況顯示:1. type_changes:類型改變的key2. values_changed:值發(fā)生變化的key3. dictionary_item_added:字典key添加4. dictionary_item_removed:字段key刪除
"""
from deepdiff import DeepDiff# 1. 字典是以key,順序沒有關(guān)系
# json1 = {"name": "hami", "age": 18}
# json2 = {"age": 18, "name": "hami"}# res = DeepDiff(json1,json2)
# print(res)# 2. 定義兩個(gè)列表進(jìn)行比較,列表有序的,按照順序去進(jìn)行對比
# list1 = [1, 2, 3]
# list2 = [3, 2, 1]# 有序列表,會(huì)返回對應(yīng)的數(shù)據(jù): {'values_changed': {'root[0]': {'new_value': 3, 'old_value': 1}, 'root[2]': {'new_value': 1, 'old_value': 3}}}
# res = DeepDiff(list1, list2)
# print(res)
# # 過濾對應(yīng)的順序: ignore_order=True ------{}
# res = DeepDiff(list1, list2, ignore_order=True)
# print(res)# 3. 過濾大小寫的操作:  ignore_string_case=True
# json1 = {"name": "hami", "age": 18}
# json2 = {"age": 18, "name": "Hami"}
#
# res = DeepDiff(json1, json2)
# print(res)
# # 過濾字符的大小寫(不區(qū)分)
# res = DeepDiff(json1, json2, ignore_string_case=True)
# print(res)# 4. 忽略某個(gè)字段  exclude_paths={"age"} --- 用的最多
json1 = {"code": "200", "name": "hami", "usercode": "431123456789", "age": 18}
json2 = {"code": "200", "name": "hami", "usercode": "431123456789", "age": 20}
res = DeepDiff(json1, json2)
print(res)
res = DeepDiff(json1, json2, exclude_paths={"age"})
# res = DeepDiff(json1, json2, exclude_paths={"root['age']"})
print(res)

? ? ? ??

? 其他參數(shù):

????????


from deepdiff import DeepDiff"""
總結(jié):
1. 當(dāng)數(shù)據(jù)沒有差異的時(shí)候: 返回是一個(gè)空字典 {}
2. 當(dāng)數(shù)據(jù)有差異的情況,會(huì)根據(jù)實(shí)際情況顯示:1. type_changes:類型改變的key2. values_changed:值發(fā)生變化的key3. dictionary_item_added:字典key添加4. dictionary_item_removed:字段key刪除
"""
from deepdiff import DeepDiff# 忽略數(shù)字
from decimal import Decimal
# 高精度的十進(jìn)制計(jì)算,避免了浮點(diǎn)數(shù)運(yùn)算中的精度丟失問題。
t1 = Decimal('10.01') # 數(shù)字類型
t2 = 10.01# print(DeepDiff(t1, t2))
# print(DeepDiff(t1, t2, ignore_numeric_type_changes=True))# 忽略字符串
res = DeepDiff(b'hello', 'hello', ignore_string_type_changes=True)
# print(res)# 打印出來的格式可以指定:
# TREE_VIEW = 'tree'
# TEXT_VIEW = 'text'  # 默認(rèn)
t1 = {"name": "yanan", "pro": {"sh": "shandong", "city": ["zibo", "weifang"]}}
t2 = {"name": "yanan", "pro": {"sh": "shandong", "city": ["taian", "weifang"]}}
# 顯示格式:tree
diff1 = DeepDiff(t1, t2, view='tree')
print(diff1)
# 默認(rèn)為text # 可讀性
diff2 = DeepDiff(t1, t2, view='text')
print(diff2)

搜索模塊

?我們使用deepdiff還可以用來搜索

????????


from deepdiff import DeepSearchobj = ["long somewhere", "string", 0, "somewhere great!"]
item = 'some' # 大小寫敏感的
ds = DeepSearch(obj, item, case_sensitive=True)
print(ds)

?

返回的結(jié)果就是其下標(biāo)值?

哈希模塊-DeepHash

????????DeepHash模塊是DeepDiff庫中的一個(gè)模塊,用于生成復(fù)雜對象的哈希值。它可以遞歸地計(jì)算對象的哈希值,并考慮對象中的差異??梢苑奖愕赜?jì)算復(fù)雜對象的哈希值,并在需要時(shí)用于對象的唯一標(biāo)識或數(shù)據(jù)校驗(yàn)等用途

????????

from deepdiff import DeepHash
#  可以把對應(yīng)的Value 轉(zhuǎn)成對應(yīng)的Hasht1 = {"name": "yanan", "pro": {"sh": "shandong", "city": ["zibo", "weifang"]}}
res = DeepHash(t1)
print(res)

?如圖顯示,輸出的結(jié)果就是一串hash值

3.全字段對比

? ? ? ? ? ? ? ? deepdiff的封裝

????????????????????????

from deepdiff import DeepDiffdef jsonDeepDiff(json1, json2, **other):"""對比json數(shù)據(jù)的一致性:param json1: 期望結(jié)果:param json2: 實(shí)際結(jié)果:param other: 你想要寫的對應(yīng)的規(guī)則:return:"""res = DeepDiff(json1, json2, **other)if res == {}:return Trueelse:return False

將deepdiff結(jié)果之前的框架? ?

???????

? ? ? ? ? ? ? ? 我們在deepdiff封裝在關(guān)鍵字封裝的類之中和對應(yīng)的測試用例中

????????????????
? ??

另外我們還要避免excel表中的值為空的情況,因此,我們需要再請求數(shù)據(jù)的地方進(jìn)行修改

????????

4.加密

核心思路:如果說對應(yīng)的參數(shù)需要進(jìn)行加密的話,在傳參的時(shí)候在key當(dāng)中通過 @ 符號進(jìn)行標(biāo)識
對我們的data對進(jìn)行遍歷,判斷key的[0] == @

例如:{"@name":"tony","@password":"123456"}

我們先把加密方法進(jìn)行封裝

????????

"""
對稱加密:加密和解密使用的是同一把鑰匙,即:使用相同的密匙對同一密碼進(jìn)行加密和解密。
常用的加密方法:DES、3DES、AES...(AES算法是目前最常用的對稱加密算法)
"""
import base64
from Crypto.Cipher import AESclass EncryptDate:# 構(gòu)造方法def __init__(self, key):#  類屬性self.key = key.encode("utf-8")  # 初始化密鑰self.length = AES.block_size  # 初始化數(shù)據(jù)塊大小 :16位self.aes = AES.new(self.key, AES.MODE_ECB)  # 初始化AES,ECB模式的實(shí)例# 截?cái)嗪瘮?shù),去除填充的字符self.unpad = lambda date: date[0:-ord(date[-1])]# 缺幾位數(shù)據(jù)就補(bǔ)齊多少位數(shù)據(jù):16的倍數(shù)def pad(self, text):  # text == tony"""#填充函數(shù),使被加密數(shù)據(jù)的字節(jié)碼長度是block_size的整數(shù)倍"""count = len(text.encode('utf-8'))  # count = 4add = self.length - (count % self.length)  # 求它們相差的位數(shù)# add = 16- (4%16)  === 16 - 4 == 12entext = text + (chr(add) * add)#  entext = “tony” + (chr(add) * 12  )  === entext == tony# print("entext的數(shù)據(jù)是:",entext)return entext# 加密函數(shù)def encrypt(self, encrData):  # 加密函數(shù)   encrData == tony (16位)res = self.aes.encrypt(self.pad(encrData).encode("utf8"))  # self.aes.encrypt(tony)msg = str(base64.b64encode(res), encoding="utf8")return msg# 解密函數(shù)def decrypt(self, decrData):  # 解密函數(shù)   XbXHJrNLwoTVcyfqM9eTgQ==# 從base64編碼轉(zhuǎn)回來res = base64.decodebytes(decrData.encode("utf8"))# 將數(shù)據(jù)進(jìn)行對應(yīng)的解密:XbXHJrNLwoTVcyfqM9eTgQ==msg = self.aes.decrypt(res).decode("utf8")# print("msg的值:",msg)# 把轉(zhuǎn)回來的數(shù)據(jù)后面的字符去掉。return self.unpad(msg)key = "1234567812345678"
ENCRYPTAES = EncryptDate(key)

然后我們再進(jìn)行加密處理

?在excel和yaml的處理py文件中?寫上對應(yīng)的方法:

    @staticmethoddef data_EncryptDateAES(data):newdata = {}  # 去掉前面@符號同時(shí)數(shù)據(jù)進(jìn)行加密for key in data:if key[0] == "@":# 需要加密處理newdata[key[1:]] = ENCRYPTAES.encrypt(data[key])else:# 不需要加密處理newdata[key] = data[key]return newdata

5.接口簽名Sign封裝

????????數(shù)字簽名是一種用于驗(yàn)證數(shù)據(jù)完整性和身份認(rèn)證的密碼學(xué)技術(shù)。它通過使用私鑰對數(shù)據(jù)進(jìn)行加密來創(chuàng)建一個(gè)唯一的數(shù)字標(biāo)識,該標(biāo)識稱為簽名。驗(yàn)證者可以使用相應(yīng)的公鑰對簽名進(jìn)行解密和驗(yàn)證,以確認(rèn)數(shù)據(jù)的完整性和真實(shí)性


token \ session \ cookie \ 簽名(sign) --- 都是用來鑒權(quán)的

它們的區(qū)別是什么?

token \ session \ cookie

token 其實(shí)用來代表是系統(tǒng)當(dāng)中的某個(gè)用戶 --- 一般正常情況下是寫在header

session \ cookie 是你發(fā)送請求的時(shí)候自帶的.瀏覽器會(huì)自帶這個(gè)對應(yīng)的數(shù)據(jù)

session \ cookie 區(qū)別是什么?

存儲位置不同: cookie -客戶端 ; session--服務(wù)端(會(huì)話)

大小限制不同: cookie - 有大小限制; session 沒有大小限制

安全隱患不同: cookie 存在安全隱患,可以攔截或找你本地文件得到你存儲的信息

時(shí)效性不同: cookie 是時(shí)效性, session關(guān)閉瀏覽器時(shí)就消失

簽名(sign) --- 是接口當(dāng)中的一個(gè)字段. 發(fā)送消息\發(fā)送文檔\保證安全性\需要在接口傳一波數(shù)據(jù).

通過算法得到一串?dāng)?shù)據(jù)(類似于token)

http://m.aloenet.com.cn/news/38745.html

相關(guān)文章:

  • 網(wǎng)站生成wap媒體公關(guān)
  • 網(wǎng)站建立數(shù)據(jù)庫連接時(shí)出錯(cuò)職業(yè)技能培訓(xùn)機(jī)構(gòu)
  • hao愛做網(wǎng)站一鍵優(yōu)化是什么意思
  • 網(wǎng)站默認(rèn)首頁友鏈購買網(wǎng)
  • 颶風(fēng)算法受影響的網(wǎng)站seo優(yōu)化主要做什么
  • 做網(wǎng)站必須注冊的商標(biāo)網(wǎng)頁生成
  • 做網(wǎng)站 創(chuàng)業(yè)seo查詢平臺
  • wordpress 彈出框企業(yè)網(wǎng)站優(yōu)化服務(wù)公司
  • 鄭州制作網(wǎng)站ihanshi河北優(yōu)化seo
  • 中原建設(shè)信息網(wǎng) 網(wǎng)站seo優(yōu)化方式包括
  • 漯河網(wǎng)站建設(shè)公司怎么建網(wǎng)站賣東西
  • 可以查企業(yè)備案的網(wǎng)站游戲推廣賺錢
  • 建設(shè)部國家標(biāo)準(zhǔn)網(wǎng)站線上銷售的方法和技巧
  • 怎么制作h5廣州seo推廣服務(wù)
  • 創(chuàng)辦一個(gè)網(wǎng)站需要多少錢百度灰色關(guān)鍵詞排名推廣
  • 南京醫(yī)院手機(jī)網(wǎng)站建設(shè)b站推廣鏈接
  • 網(wǎng)站專題頁面設(shè)計(jì)網(wǎng)絡(luò)推廣方案范文
  • 小程序appid格式東莞seo收費(fèi)
  • 過年做哪些網(wǎng)站能致富seo概念
  • 模板網(wǎng)站建設(shè)青島seo做的好的網(wǎng)站
  • 江門網(wǎng)站建設(shè)運(yùn)營團(tuán)隊(duì)蘇州網(wǎng)站建設(shè)開發(fā)公司
  • 上海網(wǎng)站免費(fèi)制作seo怎么讀
  • 薊縣網(wǎng)站建設(shè)品牌策劃公司排名
  • 哪個(gè)網(wǎng)站可以做行程表在線優(yōu)化網(wǎng)站
  • 做網(wǎng)站的職位家庭優(yōu)化大師下載
  • 吸金聚財(cái)?shù)墓久志W(wǎng)站seo整站優(yōu)化
  • 美麗鄉(xiāng)村網(wǎng)站建設(shè)模板百度搜索入口網(wǎng)址
  • 網(wǎng)站建設(shè)推廣文章百度廣告開戶流程
  • 網(wǎng)站申請內(nèi)容嗎平臺推廣是什么意思
  • 攜程電子商務(wù)網(wǎng)站建設(shè)武漢大學(xué)人民醫(yī)院精神衛(wèi)生中心