pytest-jequnauto/utils/read_files_tools/case_automatic_control.py

224 lines
8.6 KiB
Python
Raw Permalink Normal View History

2023-02-14 11:22:13 +08:00
#!/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 返回一个目录和文件名 Collectcollect_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()