feat(): 优化项目
- 更新README - 修复bug
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,3 +3,6 @@
|
|||||||
.venv/
|
.venv/
|
||||||
poetry.lock
|
poetry.lock
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
|
report
|
||||||
|
temp
|
||||||
|
logs
|
||||||
20
README.md
20
README.md
@@ -9,8 +9,26 @@
|
|||||||
...
|
...
|
||||||
|
|
||||||
## 环境搭建
|
## 环境搭建
|
||||||
|
1,安装JAVA
|
||||||
|
- 配置环境变量
|
||||||
|
```text
|
||||||
|
JAVA_HOME
|
||||||
|
java的安装路径
|
||||||
|
CLASSPATH
|
||||||
|
%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
|
||||||
|
|
||||||
|
添加Path
|
||||||
|
%JAVA_HOME%\bin
|
||||||
|
%JAVA_HOME%\jre\bin
|
||||||
|
```
|
||||||
|
|
||||||
|
2,安装allure
|
||||||
|
- 配置环境变量
|
||||||
|
```text
|
||||||
|
添加Path
|
||||||
|
allure安装目录\bin
|
||||||
|
```
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
## 使用方法
|
## 使用方法
|
||||||
|
|
||||||
|
|||||||
36
TestCases/answer/test_1_status.yaml
Normal file
36
TestCases/answer/test_1_status.yaml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
feature: 页面状态
|
||||||
|
story: 状态
|
||||||
|
title: 查询状态信息
|
||||||
|
request:
|
||||||
|
method: get
|
||||||
|
url: /answer/api/v1/connector/info
|
||||||
|
headers:
|
||||||
|
Host: 119.91.19.171:40065
|
||||||
|
Accept-Language: en_US
|
||||||
|
Accept: application/json, text/plain, */*
|
||||||
|
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0
|
||||||
|
Referer: http://119.91.19.171:40065/users/login
|
||||||
|
Accept-Encoding: gzip, deflate
|
||||||
|
extract: # 提取变量
|
||||||
|
code:
|
||||||
|
- "json"
|
||||||
|
- "$.code"
|
||||||
|
- 0
|
||||||
|
msg:
|
||||||
|
- "json"
|
||||||
|
- "$.msg"
|
||||||
|
- 0
|
||||||
|
|
||||||
|
|
||||||
|
validate:
|
||||||
|
equals: # 断言相等
|
||||||
|
状态码等于200:
|
||||||
|
- Success.
|
||||||
|
- ${msg}
|
||||||
|
|
||||||
|
parametrize: # 数据驱动测试
|
||||||
|
- [ "title","username","password","code" ] # 变量名
|
||||||
|
- [ "测试1","user1","pass1","code1" ] # 变量值
|
||||||
|
- [ "测试2","user2","pass2","code2" ] # 变量值
|
||||||
|
- [ "测试3","user3","pass3","code3" ] # 变量值
|
||||||
|
- [ "测试4","user4","pass4","code4" ] # 变量值
|
||||||
@@ -24,8 +24,8 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
session = Session(settings.base_url)
|
session = Session(settings.base_url)
|
||||||
|
|
||||||
|
|
||||||
_case_path = Path(settings.case_path)
|
_case_path = Path(settings.case_path)
|
||||||
|
|
||||||
exchanger = Exchange(settings.exchanger)
|
exchanger = Exchange(settings.exchanger)
|
||||||
|
|
||||||
|
|
||||||
@@ -41,23 +41,24 @@ class TestAPI:
|
|||||||
"""
|
"""
|
||||||
yaml_path_list = case_path.glob("**/test_*.yaml") # 搜索当前目录及其子目录下以test_开头yaml为后缀的文件
|
yaml_path_list = case_path.glob("**/test_*.yaml") # 搜索当前目录及其子目录下以test_开头yaml为后缀的文件
|
||||||
for yaml_path in yaml_path_list:
|
for yaml_path in yaml_path_list:
|
||||||
logger.info(f"load file {yaml_path=}")
|
# logger.info(f"load file {yaml_path=}")
|
||||||
|
|
||||||
file = YamlFile(yaml_path) # 自动读取yaml文件
|
file = YamlFile(yaml_path) # 自动读取yaml文件
|
||||||
case_info = CaseInfo(**file) # 校验yaml格式
|
case_info = CaseInfo(**file) # 校验yaml格式
|
||||||
|
|
||||||
logger.debug(f"case_info={case_info.to_yaml()}") # 把case_info 转成字符串,然后记录日志
|
# logger.info(f"case_info={case_info.to_yaml()}") # 把case_info 转成字符串,然后记录日志
|
||||||
|
|
||||||
case_func = cls.new_case(case_info) # 从yaml格式转换为pytest格式
|
case_func = cls.new_case(case_info) # 从yaml格式转换为pytest格式
|
||||||
print(yaml_path.name)
|
print(yaml_path.stem)
|
||||||
setattr(cls, f"{yaml_path.name}", case_func) # 把pytest格式添加到类中
|
setattr(cls, f"{yaml_path.stem}", case_func) # 把pytest格式添加到类中
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def new_case(cls, case_info: CaseInfo):
|
def new_case(cls, case_info: CaseInfo):
|
||||||
ddt_data = case_info.ddt()
|
ddt_data = case_info.ddt()
|
||||||
print(ddt_data)
|
print(ddt_data)
|
||||||
ddt_title = [data.title for data in ddt_data]
|
|
||||||
|
|
||||||
|
ddt_title = [data.title for data in ddt_data]
|
||||||
|
logger.info(f"{ddt_title=}")
|
||||||
@allure.feature(case_info.feature)
|
@allure.feature(case_info.feature)
|
||||||
@allure.story(case_info.story)
|
@allure.story(case_info.story)
|
||||||
@pytest.mark.parametrize("case_info", ddt_data, ids=ddt_title)
|
@pytest.mark.parametrize("case_info", ddt_data, ids=ddt_title)
|
||||||
|
|||||||
@@ -31,15 +31,16 @@ class Exchange:
|
|||||||
|
|
||||||
@allure.step("提取变量")
|
@allure.step("提取变量")
|
||||||
def extract(self, resp, var_name, attr, expr: str, index):
|
def extract(self, resp, var_name, attr, expr: str, index):
|
||||||
# resp中json是方法不是属性,需要手动更改为属性
|
|
||||||
resp = copy.deepcopy(resp)
|
resp = copy.deepcopy(resp)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# resp中json是方法不是属性,需要手动更改为属性
|
||||||
resp.json = resp.json()
|
resp.json = resp.json()
|
||||||
except json.decoder.JSONDecodeError:
|
except json.decoder.JSONDecodeError:
|
||||||
resp.json = {"msg": "is not json data"}
|
resp.json = {"msg": "is not json data"}
|
||||||
|
|
||||||
data = getattr(resp, attr)
|
data = getattr(resp, attr)
|
||||||
# print(data)
|
|
||||||
if expr.startswith("/"): # xpath
|
if expr.startswith("/"): # xpath
|
||||||
res = None
|
res = None
|
||||||
elif expr.startswith("$"): # jsonpath
|
elif expr.startswith("$"): # jsonpath
|
||||||
@@ -53,18 +54,20 @@ class Exchange:
|
|||||||
else: # 如果没有数据
|
else: # 如果没有数据
|
||||||
value = "not data"
|
value = "not data"
|
||||||
|
|
||||||
logger.debug(f"{var_name} = {value}") # 记录变量名和变量值
|
logger.debug(f"{var_name} = {value}") # 记录变量名和变量值
|
||||||
|
|
||||||
self.file[var_name] = value # 保存变量
|
self.file[var_name] = value # 保存变量
|
||||||
self.file.save() # 持久化存储到文件
|
self.file.save() # 持久化存储到文件
|
||||||
|
|
||||||
@allure.step("替换变量")
|
@allure.step("替换变量")
|
||||||
def replace(self, case_info: CaseInfo):
|
def replace(self, case_info: CaseInfo):
|
||||||
...
|
logger.info(case_info)
|
||||||
|
|
||||||
# 1,将case_info转换为字符串
|
# 1,将case_info转换为字符串
|
||||||
case_info_str = case_info.to_yaml()
|
case_info_str = case_info.to_yaml()
|
||||||
|
print(f"{case_info_str=}")
|
||||||
# 2,替换字符串
|
# 2,替换字符串
|
||||||
case_info_str = Template(case_info_str).render(self.file)
|
case_info_str = Template(case_info_str).render(self.file)
|
||||||
|
print(f"{case_info_str=}")
|
||||||
# 3,将字符串转换成case_info
|
# 3,将字符串转换成case_info
|
||||||
new_case_info = case_info.by_yaml(case_info_str)
|
new_case_info = case_info.by_yaml(case_info_str)
|
||||||
return new_case_info
|
return new_case_info
|
||||||
@@ -82,7 +85,7 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
# print(mock_resp.text)
|
# print(mock_resp.text)
|
||||||
# print(mock_resp.json())
|
# print(mock_resp.json())
|
||||||
exchanger = Exchange(r"E:\PyP\InterfaceAutoTest\extract.yaml")
|
exchanger = Exchange(r"D:\CNWei\CNW\InterfaceAutoTest\extract.yaml")
|
||||||
exchanger.extract(mock_resp, "name", "json", '$.name', 0)
|
exchanger.extract(mock_resp, "name", "json", '$.name', 0)
|
||||||
exchanger.extract(mock_resp, "age", "json", '$.age', 0)
|
exchanger.extract(mock_resp, "age", "json", '$.age', 0)
|
||||||
exchanger.extract(mock_resp, "data", "json", '$.data', 0)
|
exchanger.extract(mock_resp, "data", "json", '$.data', 0)
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ class CaseInfo:
|
|||||||
def ddt(self) -> list: # 返回一个列表,列表中应该包含N个注入了变量的caseInfo
|
def ddt(self) -> list: # 返回一个列表,列表中应该包含N个注入了变量的caseInfo
|
||||||
case_list = []
|
case_list = []
|
||||||
if not self.parametrize: # 没有使用数据驱动测试
|
if not self.parametrize: # 没有使用数据驱动测试
|
||||||
|
logger.info("1,执行这一步")
|
||||||
case_list.append('')
|
case_list.append('')
|
||||||
else: # 使用数据驱动测试
|
else: # 使用数据驱动测试
|
||||||
args_name = self.parametrize[0]
|
args_name = self.parametrize[0]
|
||||||
|
|||||||
@@ -9,15 +9,19 @@
|
|||||||
@date: 2025/2/23 21:34
|
@date: 2025/2/23 21:34
|
||||||
@desc:
|
@desc:
|
||||||
"""
|
"""
|
||||||
base_url = 'http://127.0.0.1:8000'
|
from pathlib import Path
|
||||||
case_path = r"E:\PyP\InterfaceAutoTest\TestCases"
|
|
||||||
exchanger = r"E:\PyP\InterfaceAutoTest\extract.yaml"
|
|
||||||
id_path =r"E:\PyP\InterfaceAutoTest\id.yaml"
|
|
||||||
|
|
||||||
db_host = '119.91.19.171' # ip
|
root_path = (Path(__file__)).resolve().parents[1]
|
||||||
|
|
||||||
|
base_url = 'http://127.0.0.1:40065'
|
||||||
|
case_path = rf"{root_path}\TestCases\answer"
|
||||||
|
exchanger = rf"{root_path}\extract.yaml"
|
||||||
|
id_path = rf"{root_path}\id.yaml"
|
||||||
|
|
||||||
|
db_host = '127.0.0.1' # ip
|
||||||
db_port = 3306 # 端口
|
db_port = 3306 # 端口
|
||||||
db_user = 'root' # 用户名
|
db_user = 'root' # 用户名
|
||||||
db_password = 'mysql_hNahSe' # 密码
|
db_password = 'password' # 密码
|
||||||
db_database = 'answer' # 库名
|
db_database = 'answer' # 库名
|
||||||
|
|
||||||
allure_epic: str = "项目名称:answer"
|
allure_epic: str = "项目名称:answer"
|
||||||
@@ -26,3 +30,7 @@ allure_story: str = "默认事件(story)"
|
|||||||
|
|
||||||
rsa_public = ""
|
rsa_public = ""
|
||||||
rsa_private = ""
|
rsa_private = ""
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print(root_path)
|
||||||
@@ -1,3 +1,2 @@
|
|||||||
code: 200
|
code: 200
|
||||||
msg: 成功。
|
msg: Success.
|
||||||
reason: base.success
|
|
||||||
|
|||||||
3
main.py
3
main.py
@@ -10,7 +10,8 @@ TestAPI.find_yaml_case() # 加载yaml文件
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
now = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
|
now = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
|
||||||
# 1,启动框架(生成临时文件)
|
# 1,启动框架(生成临时文件)
|
||||||
pytest.main([__file__, "-x", "-v"]) # -x表示有一个用例失败后面将不执行;-v表示展示用例名称;-c,配置文件所在目录:指定pytest.ini路径
|
# -x表示有一个用例失败后面将不执行;-v表示展示用例名称;-c,配置文件所在目录:指定pytest.ini路径;--alluredir=temp。指定数据生成目录
|
||||||
|
pytest.main([__file__, "-x", "-v","--alluredir=temp"])
|
||||||
# 2,生成HTML报告
|
# 2,生成HTML报告
|
||||||
os.system('allure generate temp -o report --clean') # java程序只能借助操作系统执行
|
os.system('allure generate temp -o report --clean') # java程序只能借助操作系统执行
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user