Commit 0e84b411 by Rikka

api autotest v0.1

parent 6d0dedb3
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: __init__.py
# Author: lao_zhao
# Datetime: 2025/5/9 11:10
# Description:
#
# ---------------------------------------------------------------------------
import functools
import logging
import os
import time
def __loger(file_path):
# 获取Logger对象
logger = logging.getLogger()
# 设置日志写入文件中的级别
logger.level = logging.INFO
# 创建日志文件的handler
handler = logging.FileHandler(file_path, mode="a", encoding="utf-8")
# 设置日志在文件中的写入格式
formatter = logging.Formatter('时间:%(asctime)s - 日记级别:%(levelname)s, 日志信息:%(message)s')
# 设置日志文件的日志格式
handler.setFormatter(formatter)
# 给Logger对象添加日志文件的handler
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):
# 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
\ No newline at end of file
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: __init__.py
# Author: lao_zhao
# Datetime: 2025/5/9 11:10
# Description:
#
# ---------------------------------------------------------------------------
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: db.py
# Author: lao_zhao
# Datetime: 2025/5/9 11:34
# Description:
#
# ---------------------------------------------------------------------------
import pymysql
from APIAutoTest_v3 import log_decorator
from APIAutoTest_v3.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):
"""执行删除的sql语句"""
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):
"""执行查询的sql语句,并返回查询"""
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语句错误")
\ No newline at end of file
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: read_excel.py
# Author: lao_zhao
# Datetime: 2025/5/9 14:01
# Description:
#
# ---------------------------------------------------------------------------
import openpyxl
from APIAutoTest_v3 import log_decorator
from APIAutoTest_v3.common.read_json import read_json
from APIAutoTest_v3.common.read_system_ini import ReadSystemIni
from APIAutoTest_v3.common.read_user_ini import ReadUserIni
from APIAutoTest_v3.data_config.settings import *
class ReadExcel:
@log_decorator
def __init__(self, username):
"""获取excel的路径及工作表的名称,加载工作簿获取工作表;获取所以json文件的路径,获取json文件内容的python对象"""
self.ini = ReadUserIni(username)
# 创建系统配置文件的对象
self.system_ini = ReadSystemIni()
self.case_data_dict = read_json(self.ini.get_file_path(FILE_CASE))
self.expect_data_dict = read_json(self.ini.get_file_path(FILE_EXPECT))
self.sql_data_dict = read_json(self.ini.get_file_path(FILE_SQL))
wb = openpyxl.load_workbook(self.ini.get_file_path(FILE_EXCEL))
self.ws = wb[self.ini.get_table_name(TABLE_NAME_KEY)]
@log_decorator
def __get_cell_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_cell_value(MODULE, row)
@log_decorator
def api_name(self, row):
"""根据行,获取接口名称"""
return self.__get_cell_value(API, row)
@log_decorator
def case_req(self, row):
"""根据行,获取用例的请求方法"""
return self.__get_cell_value(METHOD, row)
@log_decorator
def case_url(self, row):
"""根据行,获取用例的url"""
value = self.__get_cell_value(PATH, row)
if value:
return self.system_ini.get_host(HOST_KEY) + value
@log_decorator
def case_mime(self, row):
"""根据行,获取用例的媒体类型"""
value = self.__get_cell_value(MIME, row)
if value:
return value.lower()
@log_decorator
def case_data(self, row):
"""根据行,获取用例数据"""
case_data_key = self.__get_cell_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_cell_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语句"""
sql_data_key = self.__get_cell_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):
"""根据行,获取sql语句的类型"""
value = self.__get_cell_value(SQLTYPE, row)
if value:
return value.lower()
@log_decorator
def update_key(self, row):
"""根据行,获取更新的key"""
return self.__get_cell_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_type = self.sql_type(row)
sql_data = self.sql_data(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("zhangsan")
print(excel.get_data())
\ No newline at end of file
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: read_json.py
# Author: lao_zhao
# Datetime: 2025/5/9 11:29
# Description:
#
# ---------------------------------------------------------------------------
import json
import os
from APIAutoTest_v3 import log_decorator
@log_decorator
def read_json(file_path):
"""读取json文件,将json文件的内容序列化为python对象,再返回"""
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.loads(f.read())
else:
raise FileExistsError("json文件路径错误")
if __name__ == '__main__':
read_json(r"xxxew.json")
\ No newline at end of file
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: read_system_ini.py
# Author: lao_zhao
# Datetime: 2025/5/9 11:21
# Description:
#
# ---------------------------------------------------------------------------
import configparser
import os
from APIAutoTest_v3 import log_decorator
class ReadSystemIni:
@log_decorator
def __init__(self):
"""获取系统配置ini文件的路径,并创建Configparser对象,在读取ini文件"""
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")
@log_decorator
def get_host(self, key):
"""根据key,获取被测系统的域名"""
return self.conf.get("url", key)
@log_decorator
def get_sql_connect_msg(self, key):
"""根据key,获取数据库的链接信息"""
return self.conf.get("sql", key)
@log_decorator
def get_username(self, key):
"""根据key,获取用户存放数据的目录名称"""
return self.conf.get("user", key)
if __name__ == '__main__':
ini = ReadSystemIni()
print(ini.get_host("host"))
\ No newline at end of file
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: read_user_ini.py
# Author: lao_zhao
# Datetime: 2025/5/9 11:21
# Description:
#
# ---------------------------------------------------------------------------
import configparser
import os
from APIAutoTest_v3 import log_decorator
class ReadUserIni:
@log_decorator
def __init__(self, username):
"""获取用户配置ini文件的路径,并创建Configparser对象,在读取ini文件"""
data_config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data_config")
# 获取用例存放数据的目录路径
self.user_data_config_path = os.path.join(data_config_path, username)
ini_path = os.path.join(self.user_data_config_path, "config.ini")
self.conf = configparser.ConfigParser()
self.conf.read(ini_path, encoding="utf-8")
@log_decorator
def get_file_path(self, key):
"""根据key,获取file节点下文件的路径"""
return os.path.join(self.user_data_config_path, self.conf.get("file", key))
@log_decorator
def get_table_name(self, key):
"""根据key,获取工作表的名称"""
return self.conf.get("table", key)
if __name__ == '__main__':
ini = ReadUserIni("bpm")
print(ini.get_file_path("case"))
\ 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"
}
}
}
[file]
# 配置数据文件
# 配置用例管理文件
excel=APIAutoTest.xlsx
# 配置用例数据文件
case=case_data.json
# 配置期望数据文件
expect=expect_data.json
# 配置sql语句数据文件
sql=sql_data.json
[table]
# 配置数据表的表名
table_name = BPM
{
"认证接口": {
"登录系统": {
"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
# -*-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=zhangsan
\ No newline at end of file
[file]
# 配置数据文件
# 配置用例管理文件
excel=接口用例.xlsx
# 配置用例数据文件
case=用例数据.json
# 配置期望数据文件
expect=期望数据.json
# 配置sql语句数据文件
sql=sql语句.json
[table]
# 配置数据表的表名
table_name = 张三
{
{
"维度管理": {
"添加维度": {
"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: __init__.py
# Author: lao_zhao
# Datetime: 2025/5/9 11:10
# Description:
#
# ---------------------------------------------------------------------------
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: request_method.py
# Author: lao_zhao
# Datetime: 2025/5/9 14:17
# Description:
#
# ---------------------------------------------------------------------------
import requests
from APIAutoTest_v3 import log_decorator
from APIAutoTest_v3.common.db import DB
from APIAutoTest_v3.common.read_system_ini import ReadSystemIni
class RequestMethod:
@log_decorator
def __init__(self):
"""关联被测系统的状态"""
login_url = ReadSystemIni().get_host("host") + "/auth"
log_data = {
"username": "admin",
"password": "fWwO5OcV0c5AZfgOohpm4OE/FjKMc5wcjjaJvfbnrTIQMG5d3htn2aFA2iZGkSgYZ+9liGgmple6bCp+NT4PnY2Jlov8tV8Q/+nn2IZTuPCMwHqRrUchpPUr4wXWuQ+Gk55DNu4CZgxWQ5HxfzixGHJT29D6TUiz5Ea+mLm3fg8="
}
self.bpm_session = requests.sessions.Session()
self.header = {"Authorization": "Bearer "+self.bpm_session.request(method="post", url=login_url, json=log_data).json().get("token")}
self.bpm_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):
"""
封装一个公共的请求方法
:param req_method: 请求方法
:param req_url: 请求的url
:param req_mime: 请求的媒体类型
:param case_data: 用例数据
:param sql_type: sql语句类型
:param sql_data: sql语句
:param update_key: 更新的key
:return: Response Type
"""
# 先执行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
# 判断sql语句的类型是否为delete|select,或者为select|delete
elif sql_type == "delete|select" or sql_type == "select|delete":
# 删除执行删除的sql语句
self.db.delete(sql_data["delete"])
# 再执行查询的sql语句,获取查询结果,将查询结果更新到用例数据中
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.bpm_session.headers["content-type"] = "application/json"
if isinstance(case_data, str):
# 除了上传文件-files和发送python对象给服务器-json,以外的所以数据如果要在请求体中发送给服务器,全部使用data发送给服务器。
return self.bpm_session.request(method=req_method, url=req_url, data=case_data)
else:
return self.bpm_session.request(method=req_method, url=req_url, json=case_data)
elif req_mime == "text" or req_mime == "text/plain":
self.bpm_session.headers["content-type"] = "text/plain"
return self.bpm_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.bpm_session.headers["content-type"] = "application/x-www-form-urlencoded"
return self.bpm_session.request(method=req_method, url=req_url, data=case_data)
elif req_mime == "query":
return self.bpm_session.request(method=req_method, url=req_url, params=case_data)
# 判断媒体类型是否为query|json或者为json|query,表示请求体和地址栏同时传参
elif req_mime == "query|json" or req_mime == "json|query":
# 先取出请求体和地址栏传参的数据
body = case_data.get("body")
query = case_data.get("query")
# 更改请求的媒体类型
self.bpm_session.headers["content-type"] = "application/json"
# 判断请求的数据类型是否为字符串,如果是使用data传参,如果不是使用json传参
if isinstance(body, str):
return self.bpm_session.request(method=req_method, url=req_url, data=body, params=query)
else:
return self.bpm_session.request(method=req_method, url=req_url, json=body, params=query)
elif req_mime is None:
return self.bpm_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("媒体类型错误")
\ No newline at end of file
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: __init__.py
# Author: lao_zhao
# Datetime: 2025/5/9 11:10
# Description:
#
# ---------------------------------------------------------------------------
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: __init__.py
# Author: lao_zhao
# Datetime: 2025/5/9 14:29
# Description:
#
# ---------------------------------------------------------------------------
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: conftest.py
# Author: lao_zhao
# Datetime: 2025/5/9 14:29
# Description:
#
# ---------------------------------------------------------------------------
import pytest
from APIAutoTest_v3.request_method.request_method import RequestMethod
@pytest.fixture(scope="session")
def req_fix():
req = RequestMethod()
yield req
req.db.close()
\ No newline at end of file
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: test_bpm.py
# Author: lao_zhao
# Datetime: 2025/5/9 14:30
# Description:
#
# ---------------------------------------------------------------------------
import pytest
from APIAutoTest_v3 import log_decorator
from APIAutoTest_v3.common.read_excel import ReadExcel
from APIAutoTest_v3.common.read_system_ini import ReadSystemIni
datas = ReadExcel(ReadSystemIni().get_username("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_fix, req, url, mime, case, expect, sql_type, sql_data, update_key):
res = req_fix.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}")
\ No newline at end of file
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: __init__.py
# Author: lao_zhao
# Datetime: 2025/5/8 10:20
# Description:
#
# ---------------------------------------------------------------------------
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: conftest.py
# Author: lao_zhao
# Datetime: 2025/5/8 10:22
# Description:
#
# ---------------------------------------------------------------------------
# dependency
import pytest
from APIAutoTest_v3.request_method.request_method import RequestMethod
depend_dict = {}
@pytest.fixture(scope="session")
def req_fix():
yield RequestMethod()
@pytest.fixture(scope="session")
def depend_data_fix():
return depend_dict
# 了解
@pytest.fixture(scope="session")
def set_depend_data_fix():
def set_value(key, value):
# ...
depend_dict[key] = value
# ...
yield set_value
@pytest.fixture(scope="session")
def get_depend_data_fix():
def get_value(key):
# ...
value = depend_dict.get(key)
# ...
return value
yield get_value
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: test_auth.py
# Author: lao_zhao
# Datetime: 2025/5/8 10:20
# Description:
#
# ---------------------------------------------------------------------------
import pytest
class TestAuth:
# 登录
# 标记当前的用例被后续的用例依赖
@pytest.mark.dependency(scope="session")
def test_login(self, req_fix):
login_data = {"username": "admin",
"password": "BEYEoXxKBfk7COvpsAMhEw9laWTPr4PUoREUqe5tssyIl+omAR0uCUS5by+/Ky87hBUOvKrNQkMdHac46fInGWQ4nguGERyyG5pAfNC9rhtiM73iFU2ql2zConiIMZ8aZ9fUhSd1JK+JJnopIgUNAdpWDbG9sCnXng6HjIsD+BM="}
login_url = 'http://36.139.193.99:8088/auth'
res = req_fix.bpm_session.request(method="post", url=login_url, json=login_data)
assert "超级管理员" in res.text
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: test_dem.py
# Author: lao_zhao
# Datetime: 2025/5/8 10:21
# Description:
#
# ---------------------------------------------------------------------------
import pytest
from faker import Faker
data = Faker(locale="zh_cn")
depend_data = {}
@pytest.mark.dependency(depends=['test_bpm_dependency/test_auth.py::TestAuth::test_login'], scope="session")
def test_add_dem(req_fix):
dem_name = data.company()
dem_code = data.phone_number()
add_dem_data = {"name": dem_name,"code": dem_code,"description":""}
add_dem_url = 'http://36.139.193.99:8088/api/demension/v1/dem/addDem'
res = req_fix.bpm_session.request(method="post", url=add_dem_url, json=add_dem_data)
assert "添加维度成功" in res.text
depend_data["demCode"] = dem_code
# @pytest.mark.dependency(depends=['test_bpm/test_dem.py::test_add_dem'], scope="session")
# def test_get_dem_msg(req_fix, depend_data_fix):
# get_dem_msg_url = 'http://36.139.193.99:8088/api/demension/v1/dem/getDem'
# get_dem_msg_data = {"code": depend_data["demCode"]}
# res = req_fix.bpm_session.request(method="get", url=get_dem_msg_url, params=get_dem_msg_data)
# assert '"isDelete":"0"' in res.text
# dem_id = res.json()['id']
# depend_data_fix["DEMID"] = dem_id
@pytest.mark.dependency(depends=['test_bpm_dependency/test_dem.py::test_add_dem'], scope="session")
def test_get_dem_msg(req_fix, set_depend_data_fix):
get_dem_msg_url = 'http://36.139.193.99:8088/api/demension/v1/dem/getDem'
get_dem_msg_data = {"code": depend_data["demCode"]}
res = req_fix.bpm_session.request(method="get", url=get_dem_msg_url, params=get_dem_msg_data)
assert '"isDelete":"0"' in res.text
dem_id = res.json()['id']
set_depend_data_fix("DEMID", dem_id)
\ No newline at end of file
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: test_org.py
# Author: lao_zhao
# Datetime: 2025/5/8 10:21
# Description:
#
# ---------------------------------------------------------------------------
import pytest
from faker import Faker
data = Faker(locale="zh_cn")
'''
# 添加组织
@pytest.mark.dependency(depends=['test_bpm/test_auth.py::TestAuth::test_login', 'test_bpm/test_dem.py::test_add_dem'], scope="session")
def test_add_org(req_fix, depend_data_fix):
print(depend_data_fix["DEMID"])
add_org_url = 'http://36.139.193.99:8088/api/org/v1/org/addOrg'
add_org_data = {
"code": data.phone_number(),
"demId": depend_data_fix["DEMID"],
"exceedLimitNum": 0,
"grade": "",
"limitNum": 0,
"name": data.company(),
"nowNum": 0,
"orderNo": 0,
"parentId": "0"
}
res = req_fix.bpm_session.request(method="post", url=add_org_url, json=add_org_data)
print(res.text)
assert "成功" in res.text
'''
# 添加组织
@pytest.mark.dependency(depends=['test_bpm_dependency/test_auth.py::TestAuth::test_login', 'test_bpm_dependency/test_dem.py::test_add_dem'], scope="session")
def test_add_org(req_fix, get_depend_data_fix):
print(get_depend_data_fix("DEMID"))
add_org_url = 'http://36.139.193.99:8088/api/org/v1/org/addOrg'
add_org_data = {
"code": data.phone_number(),
"demId": get_depend_data_fix("DEMID"),
"exceedLimitNum": 0,
"grade": "",
"limitNum": 0,
"name": data.company(),
"nowNum": 0,
"orderNo": 0,
"parentId": "0"
}
res = req_fix.bpm_session.request(method="post", url=add_org_url, json=add_org_data)
print(res.text)
assert "成功" in res.text
\ No newline at end of file
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: __init__.py
# Author: lao_zhao
# Datetime: 2025/5/9 15:41
# Description:
#
# ---------------------------------------------------------------------------
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: conftest.py
# Author: lao_zhao
# Datetime: 2025/5/9 14:29
# Description:
#
# ---------------------------------------------------------------------------
import pytest
from APIAutoTest_v3.request_method.request_method import RequestMethod
@pytest.fixture(scope="session")
def req_fix():
req = RequestMethod()
yield req
req.db.close()
\ No newline at end of file
# -*-coding:utf-8 -*- #
# ---------------------------------------------------------------------------
# ProjectName: test66
# FileName: test_bpm.py
# Author: lao_zhao
# Datetime: 2025/5/9 14:30
# Description:
#
# ---------------------------------------------------------------------------
import pytest
from APIAutoTest_v3 import log_decorator
from APIAutoTest_v3.common.read_excel import ReadExcel
from APIAutoTest_v3.common.read_system_ini import ReadSystemIni
datas = ReadExcel(ReadSystemIni().get_username("user2")).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_fix, req, url, mime, case, expect, sql_type, sql_data, update_key):
res = req_fix.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}")
\ No newline at end of file
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