224 lines
8.6 KiB
Python
224 lines
8.6 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
# @Time : 2022/3/28 13:22
|
||
# @Author : 李晓杰
|
||
"""
|
||
import os
|
||
import time
|
||
from typing import Text, Dict
|
||
from common.setting import ensure_path_sep
|
||
from utils.read_files_tools.testcase_template import write_testcase_file
|
||
from utils.read_files_tools.yaml_control import GetYamlData
|
||
from utils.read_files_tools.get_all_files_path import get_all_files
|
||
from utils.other_tools.exceptions import ValueNotFoundError
|
||
|
||
|
||
class TestCaseAutomaticGeneration:
|
||
"""自动生成自动化测试中的test_case代码"""
|
||
|
||
@staticmethod
|
||
def case_date_path() -> Text:
|
||
"""返回 yaml 用例文件路径"""
|
||
return ensure_path_sep("\\data")
|
||
|
||
@staticmethod
|
||
def case_path() -> Text:
|
||
""" 存放用例代码路径"""
|
||
return ensure_path_sep("\\test_case")
|
||
|
||
def file_name(self, file: Text) -> Text:
|
||
"""
|
||
通过 yaml文件的命名,将名称转换成 py文件的名称
|
||
:param file: yaml 文件路径
|
||
:return: 示例: DateDemo.py
|
||
"""
|
||
i = len(self.case_date_path())
|
||
yaml_path = file[i:]
|
||
file_name = None
|
||
# 路径转换
|
||
if '.yaml' in yaml_path:
|
||
file_name = yaml_path.replace('.yaml', '.py')
|
||
elif '.yml' in yaml_path:
|
||
file_name = yaml_path.replace('.yml', '.py')
|
||
return file_name
|
||
|
||
def get_case_path(self, file_path: Text) -> tuple:
|
||
"""
|
||
根据 yaml 中的用例,生成对应 testCase 层代码的路径
|
||
:param file_path: yaml用例路径
|
||
:return: D:\\Project\\test_case\\test_case_demo.py, test_case_demo.py
|
||
"""
|
||
|
||
# 这里通过“\\” 符号进行分割,提取出来文件名称 os.sep表示分隔符/或者\.windows 就是\\
|
||
path = self.file_name(file_path).split(os.sep)
|
||
# 判断生成的 testcase 文件名称,需要以test_ 开头 (就是在加了个test_在前面)
|
||
case_name = path[-1] = path[-1].replace(path[-1], "test_" + path[-1])
|
||
new_name = os.sep.join(path)
|
||
# test_case目录必须在根目录pytest_auto_api2下
|
||
return ensure_path_sep("\\test_case" + new_name), case_name
|
||
|
||
def get_test_class_title(self, file_path: Text) -> Text:
|
||
"""
|
||
自动生成类名称
|
||
:param file_path:
|
||
:return: sup_apply_list --> SupApplyList
|
||
1.传入F:\JACK\My_project\pytest-auto-api2\data\Collect\collect_addtool.yaml
|
||
2.通过self.file_name(file_path) -->Collect\collect_addtool.py
|
||
3.然后os.path.split 返回一个目录和文件名 Collect,collect_addtool.py (字典)
|
||
4.通过[1][:-3] 取到第二个文件,去除.py -->collect_addtool
|
||
5.split 按"_"分隔-> colect,addtool
|
||
6.len() 获取长度 "2"
|
||
7.按长度循环遍历,把每个字符字母变大写capitalize() 将字符串的第一个字母变成大写,其他字母变小写
|
||
8.然后再拼接回去,返回
|
||
"""
|
||
# 提取文件名称
|
||
_file_name = os.path.split(self.file_name(file_path))[1][:-3]
|
||
_name = _file_name.split("_")
|
||
_name_len = len(_name)
|
||
# 将文件名称格式,转换成类名称: sup_apply_list --> SupApplyList
|
||
for i in range(_name_len):
|
||
_name[i] = _name[i].capitalize()
|
||
_class_name = "".join(_name)
|
||
# CollectToolList 'str'
|
||
return _class_name
|
||
|
||
@staticmethod
|
||
def error_message(param_name, file_path):
|
||
"""
|
||
用例中填写不正确的相关提示
|
||
:return:
|
||
"""
|
||
msg = f"用例中未找到 {param_name} 参数值,请检查新增的用例中是否填写对应的参数内容" \
|
||
"如已填写,可能是 yaml 参数缩进不正确\n" \
|
||
f"用例路径: {file_path}"
|
||
return msg
|
||
|
||
def func_title(self, file_path: Text) -> Text:
|
||
"""
|
||
函数名称
|
||
:param file_path: yaml 用例路径
|
||
:return:
|
||
"""
|
||
|
||
_file_name = os.path.split(self.file_name(file_path))[1][:-3]
|
||
return _file_name
|
||
|
||
@staticmethod
|
||
def allure_epic(case_data: Dict, file_path) -> Text:
|
||
"""
|
||
用于 allure 报告装饰器中的内容 @allure.epic("项目名称")
|
||
:param file_path: 用例路径
|
||
:param case_data: 用例数据
|
||
:return:
|
||
"""
|
||
try:
|
||
return case_data['case_common']['allureEpic']
|
||
except KeyError as exc:
|
||
raise ValueNotFoundError(TestCaseAutomaticGeneration.error_message(
|
||
param_name="allureEpic",
|
||
file_path=file_path
|
||
)) from exc
|
||
|
||
@staticmethod
|
||
def allure_feature(case_data: Dict, file_path) -> Text:
|
||
"""
|
||
用于 allure 报告装饰器中的内容 @allure.feature("模块名称")
|
||
:param file_path:
|
||
:param case_data:
|
||
:return:
|
||
"""
|
||
try:
|
||
return case_data['case_common']['allureFeature']
|
||
except KeyError as exc:
|
||
raise ValueNotFoundError(TestCaseAutomaticGeneration.error_message(
|
||
param_name="allureFeature",
|
||
file_path=file_path
|
||
)) from exc
|
||
|
||
@staticmethod
|
||
def allure_story(case_data: Dict, file_path) -> Text:
|
||
"""
|
||
用于 allure 报告装饰器中的内容 @allure.story("测试功能")
|
||
:param file_path:
|
||
:param case_data:
|
||
:return:
|
||
"""
|
||
try:
|
||
return case_data['case_common']['allureStory']
|
||
except KeyError as exc:
|
||
raise ValueNotFoundError(TestCaseAutomaticGeneration.error_message(
|
||
param_name="allureStory",
|
||
file_path=file_path
|
||
)) from exc
|
||
|
||
def mk_dir(self, file_path: Text) -> None:
|
||
""" 判断生成自动化代码的文件夹路径是否存在,如果不存在,则自动创建 """
|
||
# _LibDirPath = os.path.split(self.libPagePath(filePath))[0]
|
||
|
||
_case_dir_path = os.path.split(self.get_case_path(file_path)[0])[0]
|
||
if not os.path.exists(_case_dir_path):
|
||
os.makedirs(_case_dir_path)
|
||
|
||
@staticmethod
|
||
def case_ids(test_case):
|
||
"""
|
||
获取用例 ID
|
||
:param test_case: 测试用例内容
|
||
:return:
|
||
"""
|
||
ids = []
|
||
for k, v in test_case.items():
|
||
if k != "case_common":
|
||
ids.append(k)
|
||
# 把yaml中所有的key 都放在ids 的列表内
|
||
return ids
|
||
|
||
def yaml_path(self, file_path: Text) -> Text:
|
||
"""
|
||
生成动态 yaml 路径, 主要处理业务分层场景
|
||
:param file_path: 如业务有多个层级, 则获取到每一层/test_demo/DateDemo.py
|
||
:return: Login/common.yaml
|
||
"""
|
||
i = len(self.case_date_path())
|
||
# 兼容 linux 和 window 操作路径
|
||
yaml_path = file_path[i:].replace("\\", "/")
|
||
return yaml_path
|
||
|
||
def get_case_automatic(self) -> None:
|
||
""" 自动生成 测试代码"""
|
||
"""
|
||
1. 获取data文件下yaml文件的所有绝对路径
|
||
2. 判断是否有'proxy_data.yaml'文件,否才生成测试代码
|
||
3. 遍历调用mk_dir():里面会判断test_case 是否有test_*.py文件,没有则调用os.makedirs自动生成
|
||
4. GetYamlDate(file)
|
||
"""
|
||
# 返回的是路径一个字典
|
||
file_path = get_all_files(file_path=ensure_path_sep("\\data"), yaml_data_switch=True)
|
||
for file in file_path:
|
||
# 判断代理拦截的yaml文件,不生成test_case代码
|
||
if 'proxy_data.yaml' not in file:
|
||
# 判断用例需要用的文件夹路径是否存在,不存在则创建
|
||
self.mk_dir(file)
|
||
yaml_case_process = GetYamlData(file).get_yaml_data()
|
||
self.case_ids(yaml_case_process)
|
||
write_testcase_file(
|
||
allure_epic=self.allure_epic(case_data=yaml_case_process, file_path=file),
|
||
allure_feature=self.allure_feature(yaml_case_process, file_path=file),
|
||
# file :data\\下面的文件
|
||
class_title=self.get_test_class_title(file),
|
||
func_title=self.func_title(file),
|
||
# D:\\Project\\test_case\\test_case_demo.py
|
||
case_path=self.get_case_path(file)[0],
|
||
# yaml_case_process 是一个yaml 字典
|
||
case_ids=self.case_ids(yaml_case_process),
|
||
# test_case_demo.dy
|
||
file_name=self.get_case_path(file)[1],
|
||
allure_story=self.allure_story(case_data=yaml_case_process, file_path=file)
|
||
)
|
||
|
||
|
||
if __name__ == '__main__':
|
||
TestCaseAutomaticGeneration().get_case_automatic()
|
||
|