Python+requests+Pytest+logging+allure+pymysql框架详解

04-08 阅读 0评论

一、框架目录结构

  • 1)tools目录用来放公共方法存储,如发送接口以及读取测试数据的方法,响应断言 数据库断言 前置sql等方法;
  • 2)datas目录用例存储接口用例的测试数据,我是用excel来存储的数据,文件数据 图片数据等;
  • 3)testcases目录用来存放测试用例,一个python文件对应一个接口模块的测试用例,不同接口分别别多个不同的python文件;
  • 4)outputs里有reports和logs,report目录用来存放测试报告,报告是HTML格式的;logs是存放框架日志的;
  • 5)run.py是用来执行所有接口用例的入口文件;

二、框架结构代码图解

Python+requests+Pytest+logging+allure+pymysql框架详解

三、各文件内容详解

tools扩展封装类详解

handle_path.py :文件路径处理

from pathlib import Path
log_path = Path(__file__).absolute().parent.parent/"outputs"/"logs"/"mytest.log"
# excel表格的路径处理
exc_path = Path(__file__).absolute().parent.parent /"datas" / "testcase_mall.xlsx"
# 上传文件 路径
pic_path = Path(__file__).absolute().parent.parent /"datas"

handle_excel.py:读取excel文件内容

from pathlib import Path
from openpyxl import load_workbook
def read_data(exc_path,sheetname):
    """
    这是读取excel表格函数
    :param exc_path: 用例文件的路径
    :param sheetname: 用例表单的名字
    :return:
    """
    wb = load_workbook(exc_path)
    sh = wb[sheetname]
    cases = list(sh.values)  # 所有的用例的列表  [(第一行-title),(第二行用例),(),()]
    title = cases[0] # 得到标题行
    list_case = []
    for case in cases[1:]:
        data = dict(zip(title,case))  # 第一条用例的字典
        list_case.append(data)  # 每一条用例追加到列表里。
    return list_case
if __name__ == '__main__':
    exc_path = Path(__file__).absolute().parent.parent /"datas" / "testcase_mall.xlsx"
    print(read_data(exc_path, "登录"))

envi_data.py:存储环境变量

# 这个类就是为了存储环境变量 实现环境变量的共享的
class EnviData:
    pass

handle_replace.py
检查excel读取的内容是否需要替换变量,
需要替换变量,先提取需要替换的变量名,
再查通过需要替换的变量名在环境变量中查询对应的值
替换变量的值并返回。

"""
1、def封装
2、参数化
3、返回值: 最终要拿到替换后的字符串 ---  头部 参数 要用于发送接口测试的
4、加上日志: 但凡你想确认数据结果的地方 都可以加上日志
5、因为有些接口不需要做数据提取,所以判空处理:
6、异常捕获: 因为有可能环境变量里没有这个属性名 和属性值
"""
import re
import allure
from loguru import logger
from tools.envi_data import EnviData
from tools.handle_generate import GenData
@allure.step("替换占位符变量")
def replace_mark(str_data):
    while True:
        if str_data is None:
            return
        result = re.search("#(.*?)#",str_data)
        if result is None:  # 如果没有占位符 就是None 跳出循环
            break
        mark = result.group()  # 结果是  #prodId# --要被替换的子字符串| #gen_unregister_phone()#
        logger.info(f"要被替换的子字符串:{
     mark}")
        if "()" in mark:
            fun_name = result.group(1)  # 第一个分组的值 结果是 gen_unregister_phone()
            logger.info(f"要提取环境变量的函数名:{
     fun_name}")
            # 通过eval拖引号之后,不可以直接GenData().gen_unregister_name(),要导包
            gen_data = eval(f'GenData().{
     fun_name}')  # 接口函数的返回值结果-生成的数据
            logger.info(f"生成的随机的数据是:{
     gen_data}")
            # 1、存数据到环境变量里 -- 类属性的名字 函数名去掉()
            var_name = fun_name.strip("()")   # 结果是 gen_unregister_phone
            setattr(EnviData,var_name,gen_data)   # 属性名:gen_unregister_phone 属性值: gen_data
            logger.info(f"环境变量的属性值:{
     EnviData.__dict__}")
            # 2、完成第一条的参数的替换  用刚刚生成的数据替换
            str_data = str_data.replace(mark,str(gen_data))
            logger.info(f"替换完成后的字符串是:{
     str_data}")
        else:
            var_name = result.group(1) # 第一个分组的值 结果是 prodId
            logger.info(f"要提取环境变量的属性名:{
     var_name}")
            try:
                var_value = getattr(EnviData,var_name)  # 结果 : 7717--int类型
            except AttributeError as e:
                logger.error(f"环境变量里不存在这个属性:{
     var_name}")
                raise e
            logger.info(f"要提取环境变量的属性值:{
     var_value}")
            str_data = str_data.replac

免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,人围观)

还没有评论,来说两句吧...

目录[+]