import re
import time
import uuid
import ast
from api.conf.setting import user_info
from api.tools.handle_attribute import HandleAttr
from api.tools.handle_phone import HandlePhone
from api.conf.setting import get_mobile_code_sql
from api.tools.handle_faker import HandleFake
from api.tools.handle_db import mysql
"""
核心功能:
# 相当于jmeter中从文件读取数据,放到请求中进行参数化
# 相当于jmeter中正则表达式替换#号中的变量#(\w.+?) 参数化
\w小写的字母和数字 +?贪婪模式 ()分组匹配
(.*?)万能匹配
# 读取数据库参数化,jmeter读取数据库
# 相当于jmeter中的函数表达式str(uuid.uuid4()))生成变量
# extract_data响应结果提取token,相当于jmeter设置全局变量,jsonpath进行参数化
# excel中的setup_sql相当于jmeter中的前置处理器
# excel中的assert_db相当于jmeter中的后置处理器
"""
class HandleReplace:
def __init__(self):
# 实例化faker类,生成不重复的电话号码,用于注册
self.handle_phone = HandlePhone()
# 随机生成手机号
# self.handle_phone = HandleFake()
# 删除换行符和空格 data:str给变量data制定数据格式,好处,可以使用制定格式的方法
def __delete_space_wraps(self, data: str):
"""
:param data:excel中获取的请求参数
:return: 去掉空格和换行符的请求参数
"""
for str_data in [" ", "\n"]:
data = data.replace(str_data, "")
return data
# 获取需要替换的参数名称
def __get_replace_key(self, data):
"""
:param data: #中需要替换的变量
:return: ['user_name', 'passwd', 'sessionUUID']
"""
# 正则表达式替换#号中的变量 \w小写的字母和数字 +?贪婪模式 ()分组匹配
# (.*?)万能匹配
key_list = re.findall("#(\w.+?)#", data)
# key_list_2 = re.findall("#(.*?)#", data)
# print(key_list)
return key_list
# 根据数据的来源,获取数据,设置为类属性,往这里添加属性名称和值,传进来的key是属性名称,传入的user_info是配置文件中的字典类型
# data参数化处理替换,数据源(配置文件user_info读取,函数生成)
def __get_data_and_set_attribute(self, key: str, user_info: dict):
# 相当于jmeter中从文件读取数据,放到请求中进行参数化
# 获取需要替换的参数,来源不相同的数据,统一设置为类属性
# user_info来源配置文件:user_info["username"]["password"]
# 取值变量,通过脚本生成:'sessionUUID'
# 参数化取值来源:响应结果提取token
# 参数化取值来源数据库:mysql查询语句
# key取数来源:通过正则获取的key_list循环获取属性['user_name', 'passwd', 'session_uuid']
if key in user_info: # 如果key属性在配置文件user_info字典中['user_name', 'passwd']
# 取出来设置为类属性,给HandleAttr类添加属性
# key['user_name', 'passwd', 'session_uuid'],通过key设置为属性,拿也通过key拿
setattr(HandleAttr, key, str(user_info[key]))
# key为脚本生成['session_uuid']
# 相当于jmeter中的函数表达式
elif key == "session_uuid":
# 特殊处理,通过脚本生成:session_uuid
setattr(HandleAttr, key, str(uuid.uuid4()))
# 添加产品的唯一字段partCode,单独处理 或者支付回调bizPayNo
elif key == "partyCode" or key == "partyCode": # 后续接口无需传入partyCode
# 如果partyCode属性存在类属性中
if hasattr(HandleAttr, key):
pass
else: # 不在内属性中
setattr(HandleAttr, key, int(time.time() * 1000))
elif key == "mobile": # 判断入参是否为电话号码
if hasattr(HandleAttr, key):
pass
else: # 不在内属性中 mobile : 15217890987
# setattr(HandleAttr, key, self.handle_phone.get_phone())
setattr(HandleAttr, key, self.handle_phone.get_phone())
# 支付回调的唯一字段bizPayNo,单独处理
elif key == "bizPayNo": # 后续接口无需传入partyCode
# 如果partyCode属性存在类属性中
if hasattr(HandleAttr, key):
pass
else: # 不在内属性中
setattr(HandleAttr, key, int(time.time() * 1000))
# elif key == "valid_code": # 将短信验证码设置为内属性
# if hasattr(HandleAttr, key):
# pass
# else: # 不在内属性中 mobile : 15217890987
# # 获取短信验证码,设置为内属性
# valid_code = self.__get_valid_code()
# setattr(HandleAttr, key, valid_code)
# 通过查询数据库获取数据,然后设置为内属性,相当于jmeter后置处理,处理excel中的assert_db
def __execute_sql_and_setattr(self, sql): # key:mobile_code
# # 获取mobile获取注册手机号
# self.mobile = str(getattr(HandleAttr, "mobile"))
# # 通过配置文件读取需要替换的sql
# sql = get_mobile_code_sql["sql"].format(self.mobile)
# # 调用handle_db中的get_data查询数据,返回列表value值
# 调用sql执行方法,获取到数据result以列表嵌套字典形式显示
result = mysql.get_data_dict(sql=sql)
# 三元运算将字符串转换为dict格式
# 循环列表得到字典dict_data
for dict_data in result:
# dict.items()以列表返回可遍历的(键, 值)
for key, value in dict_data.items():
# 拿到数据并设置为属性
setattr(HandleAttr, key, str(value))
# 调用数据来源执行sql,设置属性方法,设置类属性(类似于jmeter中的前置处理器),处理excel中的setup_sql,处理data参数化,设置为类属性
def __set_attribute(self, key_list, setup_sql):
"""
:param key_list: ["user_name","session_id"]
:param setup_sql: 接口执行前,需要通过sql查询来获取替换数据,可以兼容多条
:return:
"""
# 如果excel中setup_sql字段存在
if setup_sql:
# 将读取出来的字符串,转换为列表,然后遍历列表,循环读取数据,列表兼容多条sql语句,用","隔开即可
for sql in ast.literal_eval(setup_sql):
# 通过replace_sql方法将#mobile#进行替换
new_sql = self.replace_sql(sql=sql)
# 执行sql语句,并设置为属性
self.__execute_sql_and_setattr(sql=new_sql)
else:
print(setup_sql)
for key in key_list: # key属性名称,只对excel请求参数进行属性设置,相当于jmeter后置处理
# key_list列表中的key属性名称设置为类属性
# 通过脚本生成的数据
# 响应数据
# 数据库
self.__get_data_and_set_attribute(key=key, user_info=user_info)
def replace_data(self, data, setup_sql): # 替换请求参数:data,前置处理:setup_sql参数化替换,读取sql数据生成类属性
"""
思路:
1、传入请求参数
2、删除请求参数中的换行符和空格
3、获取需要替换的参数名称:通过正则表达式返回list[]
4、每一个方法实现某一个功能
5、通过参数名称获取参数的值:统一设置为类属性
6、将参数的值替换掉参数名称和#号
:param data :str类型,excel中读取到的请求参数data
:return:
"""
if data:
# 将data中的数据去除空格和换行,返回类型str
new_data = self.__delete_space_wraps(data=data)
# print(new_data)
# 正则获取需要替换的参数名称,返回类型list ["mobile","mobile_code"}]
key_list = self.__get_replace_key(data=new_data)
# print(key_list)
# 如果key_list列表为非空,需要做参数替换
if len(key_list) > 0:
# 调用set_attribute方法将key_list,setup_sql设置为类属性
self.__set_attribute(key_list=key_list, setup_sql=setup_sql)
for key in key_list:
new_data = new_data.replace(f"#{key}#", str(getattr(HandleAttr, key)))
# 将new_data字符串转化为dict类型,可以使用ast.literal_eval()进行安全地转换。
new_data = ast.literal_eval(new_data)
# 将new_data中的t添加value值时间戳
if "t" in new_data:
new_data["t"] = int(time.time() * 1000)
else:
pass
return new_data
else:
print("无需替换数据")
# 将new_data字符串转化为dict类型,可以使用ast.literal_eval()进行安全地转换。
new_data = ast.literal_eval(new_data)
# 将new_data中的t添加value值时间戳
new_data["t"] = int(time.time() * 1000)
return new_data
else:
print("没有data传参,无需替换参数,请求为get")
return {}
# 替换查询mysql语句中的参数,替换assert_db请求参数,从类中读取属性key数据value值,替换##中的数据
def replace_sql(self, sql: str): # sql:通过excel中的assert_db读取 assert_db_info:通过setting配置文件读取
# 获取需要替换的参数名称,返回类型list
key_list = self.__get_replace_key(data=sql) # key_list等于["file_path"]
if len(key_list): # 如果key_list需要替换的数据不为空
# 获取key的值,将其设置为类属性(作用是什么?)
# for key in key_list:
# self.__get_data_and_set_attribute(key=key, user_info=assert_db_info)
for key in key_list:
# 数据来源excel读取,从类中读取属性key数据value值,替换##中的数据
sql = sql.replace(f"#{key}#", str(getattr(HandleAttr, key)))
return sql
else:
print("查询mysql语句中的参数为空,无需进行替换")
return sql
if __name__ == '__main__':
data = '{\n "t": "",\n "principal": "#user_name#",\n "credentials": "#password#",\n "sessionUUID":"#session_uuid#",\n "imageCode": "lemon"\n}'
cl = HandleReplace()
data = cl.replace_data('{\n "t": "",\n "principal": "#user_name#",\n "credentials": "#password#",\n "sessionUUID":"#session_uuid#",\n "imageCode": "lemon"\n}')
print(data)