Commit 99c32e7f by tom

first

parent 55809b81
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: __init__.py
# Author: xiao tian
# Datetime: 2025/5/9 16:54
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
import functools
import logging
import os.path
import time
def __loger(file_path):
logger = logging.getLogger()
logger.level = logging.INFO
handler = logging.FileHandler(file_path,mode="a",encoding="utf-8")
formatter = logging.Formatter('时间:%(asctime)s - 日志级别:%(levelname)s, 日志信息:%(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger
log_dir = os.path.join(os.path.join(os.path.dirname(__file__),"report"),"log")
log_name = "BPMAPITEST" + time.strftime("%Y_%m_%d_%H_%M_%S",time.localtime()) +".log"
log_path = os.path.join(log_dir,log_name)
__log = __loger(log_path)
# 定义日志的装饰器
def log_decorator(param):
@functools.wraps(param)
def inner(*args,**kwargs):
__log.info(f"执行的功能为:{param.__name__},功能的描述为:{param.__doc__},所在的文件为:{param.__code__.co_filename},所在的行为:{param.__code__.co_firstlineno}")
try:
res = param(*args,**kwargs)
except Exception as e:
__log.error(f"执行的功能为:{param.__name__}, 功能的描述为:{param.__doc__}, 所在的文件为:{param.__code__.co_filename}, 所在的行为:{param.__code__.co_firstlineno}.报错,错误为:{type(e)}, 错误的描述为:{e}")
raise e
else:
return res
return inner
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: __init__.py
# Author: xiao tian
# Datetime: 2025/5/9 17:16
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: db.py
# Author: xiao tian
# Datetime: 2025/5/10 14:56
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
import pymysql
from APIAutoTest_v3test import log_decorator
from APIAutoTest_v3test.common.read_system_ini import ReadSystemIni
class DB:
@log_decorator
def __init__(self):
ini = ReadSystemIni()
self.conn = pymysql.connect(
host=ini.get_sql_connect_msg("host"),
port=int(ini.get_sql_connect_msg("port")),
user=ini.get_sql_connect_msg("user"),
password=ini.get_sql_connect_msg("password"),
database=ini.get_sql_connect_msg("database"),
charset="utf8"
)
self.cursor = self.conn.cursor()
@log_decorator
def close(self):
self.cursor.close()
self.conn.close()
@log_decorator
def delete(self,sql_sentence):
if isinstance(sql_sentence,str) and sql_sentence.lower().startswith("delete"):
self.cursor.execute(sql_sentence)
self.conn.commit()
else:
raise ValueError("sql语句错误")
@log_decorator
def select(self,sql_sentence):
if isinstance(sql_sentence,str) and sql_sentence.lower().startswith("select"):
self.cursor.execute(sql_sentence)
select_result = self.cursor.fetchone()
if select_result:
return select_result[0]
else:
raise ValueError("sql语句错误")
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: read_excel.py
# Author: xiao tian
# Datetime: 2025/5/10 10:53
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
import openpyxl
from APIAutoTest_v3test import log_decorator
from APIAutoTest_v3test.common.read_json import read_json
from APIAutoTest_v3test.common.read_system_ini import ReadSystemIni
from APIAutoTest_v3test.common.read_user_ini import ReadUserIni
from APIAutoTest_v3test.data_config.settings import *
class ReadExcel:
@log_decorator
def __init__(self,username):
"""获取excel的路径及工作表的名称,加载工作簿获取工作表;获取所以json文件的路径,获取json文件内容的python对象"""
self.userini = ReadUserIni(username)
self.sysini = ReadSystemIni()
self.case_data_dict = read_json(self.userini.get_file_path(FILE_CASE))
self.expect_data_dict = read_json(self.userini.get_file_path(FILE_EXPECT))
self.sql_data_dict = read_json(self.userini.get_file_path(FILE_SQL))
wb = openpyxl.load_workbook(self.userini.get_file_path(FILE_EXCEL))
self.ws = wb[self.userini.get_table_name(TABLE_NAME_KEY)]
@log_decorator
def get_call_value(self,column,row):
cell_value = self.ws[column+str(row)].value
if isinstance(cell_value,str) and len(cell_value.strip())> 0 :
return cell_value.strip()
@log_decorator
def module_name(self,row):
return self.get_call_value(MODULE,row)
@log_decorator
def api_name(self,row):
return self.get_call_value(API,row)
@log_decorator
def case_req(self,row):
return self.get_call_value(METHOD,row)
@log_decorator
def case_url(self,row):
value = self.get_call_value(PATH,row)
if value:
return self.sysini.get_host(HOST_KEY) + value
@log_decorator
def case_mime(self,row):
value = self.get_call_value(MIME,row)
if value:
return value.lower()
@log_decorator
def case_data(self,row):
case_data_key = self.get_call_value(CASE,row)
module_name = self.module_name(row)
api_name = self.api_name(row)
if case_data_key and module_name and api_name:
return self.case_data_dict[module_name][api_name][case_data_key]
@log_decorator
def expect_data(self, row):
expect_data_key = self.get_call_value(EXPECT,row)
module_name = self.module_name(row)
api_name = self.api_name(row)
if expect_data_key and module_name and api_name:
return self.expect_data_dict[module_name][api_name][expect_data_key]
@log_decorator
def sql_data(self, row):
sql_data_key = self.get_call_value(SQL,row)
module_name = self.module_name(row)
api_name = self.api_name(row)
if sql_data_key and module_name and api_name:
return self.sql_data_dict[module_name][api_name][sql_data_key]
@log_decorator
def sql_type(self,row):
value = self.get_call_value(SQLTYPE,row)
if value:
return value.lower()
@log_decorator
def update_key(self,row):
return self.get_call_value(UPDATEKEY,row)
@log_decorator
def get_data(self):
list_data = []
for row in range(2,self.ws.max_row+1):
req = self.case_req(row)
url = self.case_url(row)
mime = self.case_mime(row)
case = self.case_data(row)
expect = self.expect_data(row)
sql_data = self.sql_data(row)
sql_type = self.sql_type(row)
update_key = self.update_key(row)
if req and url and expect:
list_data.append([req, url, mime, case, expect, sql_type, sql_data, update_key])
else:
return list_data
if __name__ == '__main__':
excel = ReadExcel("bpm")
print(excel.get_data())
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: read_json.py
# Author: xiao tian
# Datetime: 2025/5/10 10:23
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
import json
import os.path
from APIAutoTest_v3test import log_decorator
@log_decorator
def read_json(file_path):
if isinstance(file_path,str) and os.path.isfile(file_path) and file_path.endswith(".json"):
with open(file_path,mode="r",encoding="utf-8") as f:
return json.load(f)
else:
raise FileExistsError("JSON文件的路径")
if __name__ == '__main__':
print(read_json(r"\software\Python\pro\protest\APIAutoTest_v3test\data_config\laowang\期望数据.json"))
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: read_system_ini.py
# Author: xiao tian
# Datetime: 2025/5/10 09:42
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
import configparser
import os
from APIAutoTest_v3test import log_decorator
class ReadSystemIni:
@log_decorator
def __init__(self):
data_config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)),"data_config")
ini_path = os.path.join(data_config_path,"system_config.ini")
self.conf = configparser.ConfigParser()
self.conf.read(ini_path,encoding="utf-8")
# print(data_config_path)
# print(ini_path)
@log_decorator
def get_host(self,key):
return self.conf.get("url",key)
@log_decorator
def get_sql_connect_msg(self,key):
return self.conf.get("sql",key)
@log_decorator
def get_user(self,key):
return self.conf.get("user",key)
if __name__ == '__main__':
ini = ReadSystemIni()
print(ini.get_host("host"))
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: read_user_ini.py
# Author: xiao tian
# Datetime: 2025/5/10 09:43
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
import configparser
import os
from APIAutoTest_v3test import log_decorator
class ReadUserIni:
@log_decorator
def __init__(self,username):
data_config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)),"data_config")
self.user_path = os.path.join(data_config_path,username)
ini_path = os.path.join(self.user_path,"config.ini")
self.conf = configparser.ConfigParser()
self.conf.read(ini_path,encoding="utf-8")
@log_decorator
def get_file_path(self,key):
return os.path.join(self.user_path,self.conf.get("file",key))
@log_decorator
def get_table_name(self,key):
return self.conf.get("table",key)
if __name__ == '__main__':
ini = ReadUserIni("laowang")
print(ini.get_file_path("expect"))
print(ini.get_table_name("table_name"))
{
"认证接口": {
"登录系统": {
"LoginSuccess": {
"username": "admin",
"password": "fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8="
},
"LoginErrorPasswordParamIsClass": "{\"username\": \"admin\",class: \"fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8=\"}",
"LoginErrorPasswordParamIsNone": "{\"username\": \"admin\",: \"fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8=\"}",
"LoginErrorPasswordParamIsDouble": "{\"username\": \"admin\",\"password\": \"fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8=\",\"password\": \"123456\"}",
"LoginErrorOnlyUsername": "{\"username\": \"admin\"}",
"LoginErrorPasswordParamIsSpecial": "{\"username\": \"admin\",\"♠♣▣▤▥▦▩◘◙◈♫\": \"fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8=\"}",
"LoginErrorPasswordDataIsLong": "{\"username\": \"admin\",\"password\": \"fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8=fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8=\"}",
"LoginErrorPasswordDataIsShort": "{\"username\": \"admin\",\"password\": \"f\"}",
"LoginErrorPasswordDataIsSpecial": "{\"username\": \"admin\",\"password\": \"♠♣▣▤▥▦▩◘◙◈♫\"}",
"LoginErrorPasswordDataIsError": "{\"username\": \"admin\",\"password\": \"123456\"}",
"LoginErrorPasswordDataIsNone": "{\"username\": \"admin\",\"password\": \"\"}",
"LoginErrorPasswordDataIsClass": "{\"username\": \"admin\",\"password\": class}"
}
},
"维度管理": {
"添加维度": {
"AddDemSuccess": {
"code": "testDemension",
"description": "测试维度",
"isDefault": 0,
"name": "测试维度"
}
},
"根据维度编码获取维度信息": {
"GetDemMessageSuccess": "code=testDemension"
},
"根据维度编码删除维度": {
"DeleteDemSuccess": {"ids": "需要更新"},
"DeleteDemErrorIdsIsId": "id=需要更新"
}
},
"组织管理": {
"添加组织": {
"AddOrgSuccess": {
"code": "testAddOrg",
"demId": "需要更新",
"exceedLimitNum": 0,
"grade": "",
"limitNum": 0,
"name": "测试添加的组织",
"nowNum": 0,
"orderNo": 0,
"parentId": "0"
}
},
"保存组织参数": {
"SaveOrgParamSuccess": {
"query": "orgCode=testAddOrg",
"body": "[{\"alias\":\"test0428\",\"value\":500}]"
},
"SaveOrgParamSuccess2": {
"query": {"orgCode": "testAddOrg"},
"body": [{"alias":"test0428","value":100}]
}
},
"删除组织": {
"DelOrgSuccess": "testAddOrg"
}
}
}
[file]
excel = APIAutoTest.xlsx
case = case_data.json
expect = expect_data.json
sql = sql_data.json
[table]
table_name = BPM
\ No newline at end of file
{
"认证接口": {
"登录系统": {
"LoginSuccess": {
"username": "超级管理员",
"loginStatus": true
},
"LoginErrorPasswordParamIsClass": {
"message": "账号或密码错误"
},
"LoginErrorPasswordParamIsNone": {
"message": "账号或密码错误"
},
"LoginErrorPasswordParamIsDouble": {
"message": "账号或密码错误"
},
"LoginErrorOnlyUsername": {
"message": "账号或密码错误"
},
"LoginErrorPasswordParamIsSpecial": {
"message": "账号或密码错误"
},
"LoginErrorPasswordDataIsLong": {
"message": "账号或密码错误"
},
"LoginErrorPasswordDataIsShort": {
"message": "账号或密码错误"
},
"LoginErrorPasswordDataIsSpecial": {
"message": "账号或密码错误"
},
"LoginErrorPasswordDataIsError": {
"message": "账号或密码错误"
},
"LoginErrorPasswordDataIsNone": {
"message": "账号或密码错误"
},
"LoginErrorPasswordDataIsClass": {
"message": "账号或密码错误"
}
},
"刷新token": {
"RefreshSuccess": {
"message": "刷新成功"
}
}
},
"维度管理": {
"添加维度": {
"AddDemSuccess": {"message": "添加维度成功"}
},
"根据维度编码获取维度信息": {
"GetDemMessageSuccess": {"isDelete": "0"}
},
"根据维度编码删除维度": {
"DeleteDemSuccess": {"message": "删除维度成功"},
"DeleteDemErrorIdsIsId": {"message": "删除维度失败"}
}
},
"组织管理": {
"添加组织": {
"AddOrgSuccess": {"message": "添加组织成功!"}
},
"保存组织参数": {
"SaveOrgParamSuccess": {"state":true,"message":"保存组织参数成功!","value":"","code":200},
"SaveOrgParamSuccess2": {"state":true,"message":"保存组织参数成功!","value":"","code":200}
},
"删除组织": {
"DelOrgSuccess": {"state":true,"message":"删除组织成功!","value":"","code":200}
}
}
}
\ No newline at end of file
{
"维度管理": {
"添加维度": {
"AddDemSuccess": "delete from uc_demension where CODE_=\"testDemension\";"
},
"根据维度编码删除维度": {
"DeleteDemSuccess": "select ID_ from uc_demension where CODE_=\"testDemension\";",
"DeleteDemErrorIdsIsId": "select ID_ from uc_demension where CODE_=\"testDemension\";"
}
},
"组织管理": {
"添加组织": {
"AddOrgSuccess": {
"select": "select ID_ from uc_demension where CODE_=\"testDemension\";",
"delete": "delete from uc_org where CODE_=\"testAddOrg\";"
}
}
}
}
\ No newline at end of file
[file]
sql = sql语句.json
excel = 接口用例.xlsx
expect = 期望数据.json
case = 用例数据.json
[table]
table_name =laowang
{
{
"维度管理": {
"添加维度": {
"AddDemSuccess": "delete from uc_demension where CODE_=\"testDemension\";"
},
"根据维度编码删除维度": {
"DeleteDemSuccess": "select ID_ from uc_demension where CODE_=\"testDemension\";",
"DeleteDemErrorIdsIsId": "select ID_ from uc_demension where CODE_=\"testDemension\";"
}
},
"组织管理": {
"添加组织": {
"AddOrgSuccess": {
"select": "select ID_ from uc_demension where CODE_=\"testDemension\";",
"delete": "delete from uc_org where CODE_=\"testAddOrg\";"
}
}
}
}
\ No newline at end of file
{
{
"认证接口": {
"登录系统": {
"LoginSuccess": {
"username": "超级管理员",
"loginStatus": true
},
"LoginErrorPasswordParamIsClass": {
"message": "账号或密码错误"
},
"LoginErrorPasswordParamIsNone": {
"message": "账号或密码错误"
},
"LoginErrorPasswordParamIsDouble": {
"message": "账号或密码错误"
},
"LoginErrorOnlyUsername": {
"message": "账号或密码错误"
},
"LoginErrorPasswordParamIsSpecial": {
"message": "账号或密码错误"
},
"LoginErrorPasswordDataIsLong": {
"message": "账号或密码错误"
},
"LoginErrorPasswordDataIsShort": {
"message": "账号或密码错误"
},
"LoginErrorPasswordDataIsSpecial": {
"message": "账号或密码错误"
},
"LoginErrorPasswordDataIsError": {
"message": "账号或密码错误"
},
"LoginErrorPasswordDataIsNone": {
"message": "账号或密码错误"
},
"LoginErrorPasswordDataIsClass": {
"message": "账号或密码错误"
}
},
"刷新token": {
"RefreshSuccess": {
"message": "刷新成功"
}
}
},
"维度管理": {
"添加维度": {
"AddDemSuccess": {"message": "添加维度成功"}
},
"根据维度编码获取维度信息": {
"GetDemMessageSuccess": {"isDelete": "0"}
},
"根据维度编码删除维度": {
"DeleteDemSuccess": {"message": "删除维度成功"},
"DeleteDemErrorIdsIsId": {"message": "删除维度失败"}
}
},
"组织管理": {
"添加组织": {
"AddOrgSuccess": {"message": "添加组织成功!"}
},
"保存组织参数": {
"SaveOrgParamSuccess": {"state":true,"message":"保存组织参数成功!","value":"","code":200},
"SaveOrgParamSuccess2": {"state":true,"message":"保存组织参数成功!","value":"","code":200}
},
"删除组织": {
"DelOrgSuccess": {"state":true,"message":"删除组织成功!","value":"","code":200}
}
}
}
\ No newline at end of file
{
{
"认证接口": {
"登录系统": {
"LoginSuccess": {
"username": "admin",
"password": "fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8="
},
"LoginErrorPasswordParamIsClass": "{\"username\": \"admin\",class: \"fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8=\"}",
"LoginErrorPasswordParamIsNone": "{\"username\": \"admin\",: \"fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8=\"}",
"LoginErrorPasswordParamIsDouble": "{\"username\": \"admin\",\"password\": \"fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8=\",\"password\": \"123456\"}",
"LoginErrorOnlyUsername": "{\"username\": \"admin\"}",
"LoginErrorPasswordParamIsSpecial": "{\"username\": \"admin\",\"♠♣▣▤▥▦▩◘◙◈♫\": \"fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8=\"}",
"LoginErrorPasswordDataIsLong": "{\"username\": \"admin\",\"password\": \"fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8=fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8=\"}",
"LoginErrorPasswordDataIsShort": "{\"username\": \"admin\",\"password\": \"f\"}",
"LoginErrorPasswordDataIsSpecial": "{\"username\": \"admin\",\"password\": \"♠♣▣▤▥▦▩◘◙◈♫\"}",
"LoginErrorPasswordDataIsError": "{\"username\": \"admin\",\"password\": \"123456\"}",
"LoginErrorPasswordDataIsNone": "{\"username\": \"admin\",\"password\": \"\"}",
"LoginErrorPasswordDataIsClass": "{\"username\": \"admin\",\"password\": class}"
}
},
"维度管理": {
"添加维度": {
"AddDemSuccess": {
"code": "testDemension",
"description": "测试维度",
"isDefault": 0,
"name": "测试维度"
}
},
"根据维度编码获取维度信息": {
"GetDemMessageSuccess": "code=testDemension"
},
"根据维度编码删除维度": {
"DeleteDemSuccess": {"ids": "需要更新"},
"DeleteDemErrorIdsIsId": "id=需要更新"
}
},
"组织管理": {
"添加组织": {
"AddOrgSuccess": {
"code": "testAddOrg",
"demId": "需要更新",
"exceedLimitNum": 0,
"grade": "",
"limitNum": 0,
"name": "测试添加的组织",
"nowNum": 0,
"orderNo": 0,
"parentId": "0"
}
},
"保存组织参数": {
"SaveOrgParamSuccess": {
"query": "orgCode=testAddOrg",
"body": "[{\"alias\":\"test0428\",\"value\":500}]"
},
"SaveOrgParamSuccess2": {
"query": {"orgCode": "testAddOrg"},
"body": [{"alias":"test0428","value":100}]
}
},
"删除组织": {
"DelOrgSuccess": "testAddOrg"
}
}
}
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: settings.py
# Author: lao_zhao
# Datetime: 2025/5/9 16:07
# Description:
#
# ---------------------------------------------------------------------------
# 配置excel的列号
NUMBER = "A"
MODULE = "B"
API = "C"
TITLE = "D"
LEVEL = "E"
METHOD = "F"
PATH = "G"
MIME = "H"
CASE = "I"
EXPECT = "J"
SQLTYPE = "K"
SQL = "L"
UPDATEKEY = "M"
# 配置用户ini文件file节点下的key名
FILE_CASE = "case"
FILE_EXPECT = "expect"
FILE_EXCEL = "excel"
FILE_SQL = "sql"
# 配置用户ini文件table节点下的key名
TABLE_NAME_KEY = 'table_name'
# 配置系统配置文件下host节点下的key
HOST_KEY = 'host'
\ No newline at end of file
[url]
host=http://36.139.193.99:8088
[sql]
host=36.139.193.99
port=3306
database=eip8
user = root
password = Rhrc@2024
[user]
user1 = bpm
user2 = laowang
body {
font-family: Helvetica, Arial, sans-serif;
font-size: 12px;
/* do not increase min-width as some may use split screens */
min-width: 800px;
color: #999;
}
h1 {
font-size: 24px;
color: black;
}
h2 {
font-size: 16px;
color: black;
}
p {
color: black;
}
a {
color: #999;
}
table {
border-collapse: collapse;
}
/******************************
* SUMMARY INFORMATION
******************************/
#environment td {
padding: 5px;
border: 1px solid #e6e6e6;
vertical-align: top;
}
#environment tr:nth-child(odd) {
background-color: #f6f6f6;
}
#environment ul {
margin: 0;
padding: 0 20px;
}
/******************************
* TEST RESULT COLORS
******************************/
span.passed,
.passed .col-result {
color: green;
}
span.skipped,
span.xfailed,
span.rerun,
.skipped .col-result,
.xfailed .col-result,
.rerun .col-result {
color: orange;
}
span.error,
span.failed,
span.xpassed,
.error .col-result,
.failed .col-result,
.xpassed .col-result {
color: red;
}
.col-links__extra {
margin-right: 3px;
}
/******************************
* RESULTS TABLE
*
* 1. Table Layout
* 2. Extra
* 3. Sorting items
*
******************************/
/*------------------
* 1. Table Layout
*------------------*/
#results-table {
border: 1px solid #e6e6e6;
color: #999;
font-size: 12px;
width: 100%;
}
#results-table th,
#results-table td {
padding: 5px;
border: 1px solid #e6e6e6;
text-align: left;
}
#results-table th {
font-weight: bold;
}
/*------------------
* 2. Extra
*------------------*/
.logwrapper {
max-height: 230px;
overflow-y: scroll;
background-color: #e6e6e6;
}
.logwrapper.expanded {
max-height: none;
}
.logwrapper.expanded .logexpander:after {
content: "collapse [-]";
}
.logwrapper .logexpander {
z-index: 1;
position: sticky;
top: 10px;
width: max-content;
border: 1px solid;
border-radius: 3px;
padding: 5px 7px;
margin: 10px 0 10px calc(100% - 80px);
cursor: pointer;
background-color: #e6e6e6;
}
.logwrapper .logexpander:after {
content: "expand [+]";
}
.logwrapper .logexpander:hover {
color: #000;
border-color: #000;
}
.logwrapper .log {
min-height: 40px;
position: relative;
top: -50px;
height: calc(100% + 50px);
border: 1px solid #e6e6e6;
color: black;
display: block;
font-family: "Courier New", Courier, monospace;
padding: 5px;
padding-right: 80px;
white-space: pre-wrap;
}
div.media {
border: 1px solid #e6e6e6;
float: right;
height: 240px;
margin: 0 5px;
overflow: hidden;
width: 320px;
}
.media-container {
display: grid;
grid-template-columns: 25px auto 25px;
align-items: center;
flex: 1 1;
overflow: hidden;
height: 200px;
}
.media-container--fullscreen {
grid-template-columns: 0px auto 0px;
}
.media-container__nav--right,
.media-container__nav--left {
text-align: center;
cursor: pointer;
}
.media-container__viewport {
cursor: pointer;
text-align: center;
height: inherit;
}
.media-container__viewport img,
.media-container__viewport video {
object-fit: cover;
width: 100%;
max-height: 100%;
}
.media__name,
.media__counter {
display: flex;
flex-direction: row;
justify-content: space-around;
flex: 0 0 25px;
align-items: center;
}
.collapsible td:not(.col-links) {
cursor: pointer;
}
.collapsible td:not(.col-links):hover::after {
color: #bbb;
font-style: italic;
cursor: pointer;
}
.col-result {
width: 130px;
}
.col-result:hover::after {
content: " (hide details)";
}
.col-result.collapsed:hover::after {
content: " (show details)";
}
#environment-header h2:hover::after {
content: " (hide details)";
color: #bbb;
font-style: italic;
cursor: pointer;
font-size: 12px;
}
#environment-header.collapsed h2:hover::after {
content: " (show details)";
color: #bbb;
font-style: italic;
cursor: pointer;
font-size: 12px;
}
/*------------------
* 3. Sorting items
*------------------*/
.sortable {
cursor: pointer;
}
.sortable.desc:after {
content: " ";
position: relative;
left: 5px;
bottom: -12.5px;
border: 10px solid #4caf50;
border-bottom: 0;
border-left-color: transparent;
border-right-color: transparent;
}
.sortable.asc:after {
content: " ";
position: relative;
left: 5px;
bottom: 12.5px;
border: 10px solid #4caf50;
border-top: 0;
border-left-color: transparent;
border-right-color: transparent;
}
.hidden, .summary__reload__button.hidden {
display: none;
}
.summary__data {
flex: 0 0 550px;
}
.summary__reload {
flex: 1 1;
display: flex;
justify-content: center;
}
.summary__reload__button {
flex: 0 0 300px;
display: flex;
color: white;
font-weight: bold;
background-color: #4caf50;
text-align: center;
justify-content: center;
align-items: center;
border-radius: 3px;
cursor: pointer;
}
.summary__reload__button:hover {
background-color: #46a049;
}
.summary__spacer {
flex: 0 0 550px;
}
.controls {
display: flex;
justify-content: space-between;
}
.filters,
.collapse {
display: flex;
align-items: center;
}
.filters button,
.collapse button {
color: #999;
border: none;
background: none;
cursor: pointer;
text-decoration: underline;
}
.filters button:hover,
.collapse button:hover {
color: #ccc;
}
.filter__label {
margin-right: 10px;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: __init__.py
# Author: xiao tian
# Datetime: 2025/5/9 17:16
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: request_method.py
# Author: xiao tian
# Datetime: 2025/5/10 15:18
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
import requests
from APIAutoTest_v3test import log_decorator
from APIAutoTest_v3test.common.db import DB
from APIAutoTest_v3test.common.read_system_ini import ReadSystemIni
class RequestMethod:
# @log_decorator
def __init__(self):
login_url = ReadSystemIni().get_host("host") + "/auth"
login_data = {
"username": "admin",
"password": "fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8="
}
self.session = requests.sessions.Session()
self.header = {"Authorization": "Bearer "+self.session.request(method="post",url=login_url,json=login_data).json().get("token")}
self.session.headers.update(self.header)
self.db = DB()
@log_decorator
def request_all(self,req_method, req_url, req_mime, case_data, sql_type, sql_data, update_key):
# 先执行sql语句---该删除的就删除,如果有查询就需要更新用例数据,更新时,需要注意用例数据的类型
if sql_type =="delete":
self.db.delete(sql_data)
elif sql_type == "select":
select_result = self.db.select(sql_data)
if isinstance(case_data,str):
case_data=case_data.replace(update_key,select_result)
else:
case_data[update_key]= select_result
elif sql_type =="delete|select" or sql_type == "select|delete":
self.db.delete(sql_data["delete"])
select_result = self.db.select(sql_data["select"])
if isinstance(case_data, str):
case_data = case_data.replace(update_key, select_result)
else:
case_data[update_key] = select_result
# 后发送请求--判断媒体类型,不同的媒体类型使用不同的关键字传参
if req_mime =="json" or req_mime =="application/json":
self.session.headers["content-type"] = "application/json"
if isinstance(case_data,str) :
return self.session.request(method=req_method,url=req_url,data=case_data)
else:
return self.session.request(method=req_method,url=req_url,json=case_data)
elif req_mime =="text" or req_mime =="text/plain":
self.session.headers["content-type"] = "text/plain"
return self.session.request(method=req_method,url=req_url,data=case_data)
elif req_mime =="form" or req_mime =="x-www-form-urlencoded" or req_mime == "application/x-www-form-urlencoded":
self.session.headers["content-type"] = "application/x-www-form-urlencoded"
return self.session.request(method=req_method,url=req_url,data=case_data)
elif req_mime =="query":
return self.session.request(method=req_method,url=req_url,params=case_data)
elif req_mime == "query|json" or req_mime == "json|query":
body = case_data.get("body")
query = case_data.get("query")
self.session.headers["content-type"] = "application/json"
if isinstance(case_data, str):
return self.session.request(method=req_method, url=req_url, data=body, params=query)
else:
return self.session.request(method=req_method, url=req_url, json=body, params=query)
elif req_mime is None:
return self.session.request(method=req_method,url=req_url)
elif req_mime =="multipart/form-data" or req_mime == "form-data":
return requests.request(method=req_method,url=req_url,files = case_data,headers=self.header)
else:
raise ValueError("媒体类型的错误")
if __name__ == '__main__':
req = RequestMethod()
print(type(req), req)
\ No newline at end of file
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: __init__.py
# Author: xiao tian
# Datetime: 2025/5/9 17:16
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: conftest.py
# Author: lao_zhao
# Datetime: 2025/5/12 10:00
# Description:
#
# ---------------------------------------------------------------------------
# def pytest_collection_modifyitems(items):
# # item表示每个测试用例,解决用例名称中文显示问题
# for item in items:
# item.name = item.name.encode("utf-8").decode("unicode-escape")
# item._nodeid = item._nodeid.encode("utf-8").decode("unicode-escape")
\ No newline at end of file
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: __init__.py
# Author: xiao tian
# Datetime: 2025/5/10 16:26
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: conftest.py
# Author: xiao tian
# Datetime: 2025/5/10 16:27
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
import pytest
from APIAutoTest_v3test.request_method.request_method import RequestMethod
@pytest.fixture(scope="session")
def req_fix1():
req = RequestMethod()
yield req
req.db.close()
\ No newline at end of file
# -*-coding:utf-8 -*- #
# --------------------------------------------------------------------------
# ProjectName: protest
# FileName: test_bpm.py
# Author: xiao tian
# Datetime: 2025/5/10 16:26
# Description:
# 命名规范:文件名全小写+下划线,类名大驼峰,方法和变量小写+下划线连接,
# 常量大写,变量和常量用名词,方法用动词
# --------------------------------------------------------------------------
import pytest
from APIAutoTest_v3test import log_decorator
from APIAutoTest_v3test.common.read_excel import ReadExcel
from APIAutoTest_v3test.common.read_system_ini import ReadSystemIni
from APIAutoTest_v3test.request_method.request_method import RequestMethod
datas = ReadExcel(ReadSystemIni().get_user("user1")).get_data()
class TestBPM:
@log_decorator
@pytest.mark.parametrize("req, url, mime, case, expect, sql_type, sql_data, update_key", datas)
def test_bpm (self, req_fix1, req, url, mime, case, expect, sql_type, sql_data, update_key):
res = req_fix1.request_all(req_method=req,req_url=url,req_mime=mime,case_data=case,sql_type=sql_type,sql_data=sql_data,update_key=update_key)
try:
for key in expect:
assert expect[key] == res.json().get(key)
except AssertionError :
raise AssertionError(f"断言失败,\n\t请求的url为:{url}, \n\t用例数据为:{case}, \n\t期望数据为:{expect}, \n\t服务器返回的数据为:{res.text}")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment