123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- # -*- coding: utf-8 -*-
- import ast
- import copy
- import json
- import os.path
- # 专门用例Excel参数化
- # 导入excel的包:pip install pandas
- # openpyxl是pandas用于读取.xlsx文件的引擎之一
- # pip install pandas openpyxl
- # 读取yaml的数据
- import yaml, os, uuid
- import pandas as pd
- from apirun.core.globalContext import g_context
- from apirun.Log.Log import logger
- def load_context_from_excel(folder_path):
- """
- :param folder_path: 文件路径
- :return:
- """
- try:
- excel_file_path = os.path.join(folder_path, "context.xlsx") # 把2个文本进行拼接
- # 读取excel
- df = pd.read_excel(excel_file_path)
- # 初始化一个变量进行存储
- data = {
- "_database": {}
- }
- for index, row in df.iterrows():
- # 如果是变量我们就直接存在:变量名:value
- if row["类型"] == "变量":
- data[row["变量描述"]] = row["变量值"]
- elif row["类型"] == "数据库":
- db_name = row["变量描述"]
- db_config = json.loads(row["变量值"]) # 变成字典格式
- data["_database"][db_name] = db_config
- if data: g_context().set_by_dict(data) # 写入到全局变量
- except Exception as e:
- logger.error(f"装载excel文件错误: {str(e)}")
- return False
- # 加载我们满足条件的文件及数据
- def load_excel_files(config_path):
- """
- 返回满足条件的excel文件列表及数据
- :param config_path: excel存放的路径
- :return:
- """
- excel_caseInfos = [] # 存储所有的数据
- suite_folder = os.path.join(config_path)
- # 存放在该路径的全局变量进行写入
- load_context_from_excel(suite_folder)
- # 满足条件的列表
- file_names = [(int(f.split("_")[0]), f) for f in os.listdir(suite_folder) if
- f.endswith(".xlsx") and f.split("_")[0].isdigit()]
- # 排序,排序只保留文件名即可
- file_names.sort()
- file_names = [f[-1] for f in file_names]
- # 读取我们维护的yaml数据,方便后面和值一一对应起来
- current_dir = os.path.abspath(os.path.dirname(__file__)) # 获取当前文件的绝对路径
- parent_dir = os.path.dirname(current_dir) # 基于当前路径获取上一层路径
- keywords_file_path = os.path.join(parent_dir, "extend/keywords.yaml") # 进行拼接
- keywords_info = {}
- with open(keywords_file_path, "r", encoding="utf-8") as f:
- keywords_info = yaml.full_load(f) #
- # 加载每个文件的数据给到yaml_caseInfos
- for file_name in file_names:
- file_path = os.path.join(suite_folder, file_name)
- # TODO 1: 读取excel
- lr =[]
- for i in pd.ExcelFile(file_path).sheet_names: # 遍历excel表格的sheet页名称
- if i != '关键字说明':
- data = pd.read_excel(file_path, sheet_name=i) # 获取单个sheet页的全量数据
- data = data.where(data.notnull(), None) # 将非空值保留,空数据用None替换
- data = data.to_dict(orient='records') # 用一个大列表把没一行编成一个字典元素,存储起来
- lr.extend(data)
- # 初始化一个字典,用例存放某一条测试用例
- current_test_case = None
- for row in lr:
- # 判断是否有测试标题:如果有的话,代表是我们第一个,直到遇到下一个标题,就从头开头
- # TODO 1: # 检查当前行是否包含有效的测试用例标题,有则代表对应的起始位
- if pd.notna(row["测试用例标题"]):
- # 如果已经构建完毕那么需要当前加进去到对应的测试用例当中
- if current_test_case is not None:
- excel_caseInfos.append(current_test_case)
- # 初始化一个测试用例字典
- current_test_case = {
- "process": row['进程类'],
- "desc": row['测试用例标题'],
- "featureName": row['一级模块'],
- "storyName": row['二级模块'],
- "steps": []
- }
- # TODO 2-1: 初始化步骤的值
- steps = {
- row["步骤描述"]: {
- "关键字": row["关键字"]
- }
- }
- # TODO 2-2: 考虑步骤当中对应的每个参数。
- parameter = []
- for key, value in row.items():
- if "参数_" in key:
- try:
- # 尝试将字符串转换为Python对象
- value = ast.literal_eval(value)
- except:
- pass
- parameter.append(value)
- # TODO 2-3: 把对应的值和KEY一一对应起来,这样我们才能发送请求 -zip
- dict_parameter = {k: v for k, v in zip(keywords_info[row["关键字"]], parameter)}
- steps[row["步骤描述"]].update(dict_parameter)
- # 步骤加到当前测试用例来
- current_test_case["steps"].append(steps)
- if current_test_case is not None:
- excel_caseInfos.append(current_test_case)
- return excel_caseInfos
- # 把yaml的格式处理成我们规定的格式
- def excel_case_parser(config_path):
- """
- 返回指定条件的格式
- :param config_path: 文件的路径
- :return: {
- "case_infos": case_infos, # 所有的测试用例 []
- "case_names": case_names # 所有测试用例对应的标题 []
- }
- """
- # TODO 0: 对应固定的格式
- case_infos = []
- case_names = []
- case_process = []
- # TODO 1: 调用对应的方法:拿到所有的用例数据
- excel_caseInfos = load_excel_files(config_path)
- # TODO 2: 统一处理成一样的格式 (后面excel一样的处理)
- for caseinfo in excel_caseInfos:
- caseinfo.update({"_case_name": caseinfo["desc"]})
- case_infos.append(caseinfo) # 所有的测试用例 []
- case_names.append(caseinfo["desc"]) # 所有的用例名称 []
- case_process.append(caseinfo["process"]) # 所有的用例使用的进程 []
- return {
- "case_infos": case_infos,
- "case_names": case_names,
- "case_process": case_process
- }
- # data = excel_case_parser(r"D:\001_zzh\eng\api-engine\examples\examples-dsw")
- # print(data)
|