【day8】调用AI接口,生成自动化测试用例

news2025/4/21 3:23:20

1、项目结构建议

project/
├── api_docs/ # 存放接口文档
│ └── XX系统.swagger.json
├── ai_generator/ # AI测试用例生成模块
│ └── test_case_generator.py
├── tests/ # 生成的测试用例
│ └── test_user_api.py
├── conftest.py # pytest配置
├── url/ # 存放url
│ └── xx模块url.py
└── requirements.txt

XX系统.swagger.json来源
在这里插入图片描述

2、新增空的xx模块url.py

在这里插入图片描述

3、编写自动化封装api的脚本,自动化生成测试用例

这里需要安装第三方库zhipuai
可以借鉴:https://blog.csdn.net/weixin_41665637/article/details/147113443?

import requests
from zhipuai import ZhipuAI
import json
import re
import logging
from pathlib import Path
from typing import Dict, List, Optional, Any
from dataclasses import dataclass
from faker import Faker

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


@dataclass
class APIEndpoint:
    path: str
    method: str
    summary: str
    parameters: List[Dict[str, Any]]
    operation_id: Optional[str] = None


class TestCaseGenerator:
    def __init__(self, api_key: str, base_url: str = ""):
        self.client = ZhipuAI(api_key=api_key)
        self.faker = Faker('zh_CN')
        self.base_url = base_url.strip('/')

        self.test_template = """import pytest
import requests
import logging
from faker import Faker
from api.urls import AuthUrls
from api.merchant_urls import MerchantUrls
from test_data.auth_params import valid_credentials
from config.settings import get_base_url

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class TestGeneratedCases:
    @pytest.fixture(scope="class")
    def auth_token(self):
        url = AuthUrls().login
        response = requests.post(url, json=valid_credentials)
        assert response.status_code == 200
        return response.json()["token"]

    {test_methods}
"""

    def generate_test_cases(self, swagger_data: Dict, output_path: str):
        """生成完整测试用例文件"""
        endpoints = self._parse_swagger(swagger_data)
        test_methods = "\n\n    ".join([self._generate_test_method(endpoint) for endpoint in endpoints])
        test_file = self.test_template.format(test_methods=test_methods)
        self._save_to_file(output_path, test_file)

    def _parse_swagger(self, swagger_data: Dict) -> List[APIEndpoint]:
        """解析Swagger文档"""
        endpoints = []
        for path, methods in swagger_data["paths"].items():
            for method, details in methods.items():
                endpoint = APIEndpoint(
                    path=path,
                    method=method.upper(),
                    summary=details.get("summary", "No description"),
                    parameters=details.get("parameters", []),
                    operation_id=details.get("operationId")
                )
                endpoints.append(endpoint)
        return endpoints

    def _generate_test_method(self, endpoint: APIEndpoint) -> str:
        """生成单个测试方法"""
        method_name = self._generate_method_name(endpoint)
        path_params = self._parse_path_params(endpoint.path)
        query_params = [p["name"] for p in endpoint.parameters if p.get("in") == "query"]
        body_params = [p["name"] for p in endpoint.parameters if p.get("in") == "body"]

        # 生成URL(使用正确的方法名和参数)
        url = self._generate_full_url(
            base_path=endpoint.path,
            path_params=path_params
        )

        # 生成请求参数(暂时简化处理)
        request_params = self._build_request_params(
            method=endpoint.method.lower(),
            path_params=path_params,
            query_params=query_params,
            body_params=body_params
        )
        return f'''
    @pytest.mark.{endpoint.method.lower()}
    def {method_name}(self, auth_token):
        """{endpoint.summary}"""
        
        # 生成URL
        url =get_base_url()+"{url}"
        # 生成请求参数
        request_params ={request_params}
        headers = {{"Authorization": f"Bearer {{auth_token}}"}}
        response = requests.{endpoint.method.lower()}(
                url,
                headers=headers,
                json=request_params
            )
        assert 200 == response.status_code
'''
    def _parse_request_body(self, parameters: List) -> Dict:
        """深度解析请求体结构"""
        body_params = next((p for p in parameters if p.get('in') == 'body'), None)
        if not body_params:
            return {}

        schema = body_params.get('schema', {})
        if '$ref' in schema:
            return self._resolve_ref(schema['$ref'])
        return self._parse_schema(schema)

    def _generate_smart_data(self, schema: Dict) -> Dict:
        """生成符合schema的智能数据"""
        # 实现递归数据生成逻辑
        pass

    def _build_request_params(self, method: str, path_params: list, query_params: list, body_params: list) -> dict:
        """构建请求参数字典"""
        params = []
        # 路径参数处理
        if path_params:
            params.append(f"params={{'{path_params[0]}': self.faker.uuid4()}}")
        if method in ['post', 'put', 'patch'] and body_params:
            params.append(f"json={{'{body_params[0]}': self.faker.word()}}")
        return ",\n                ".join(params)


    def _generate_full_url(self, base_path: str, path_params: list) -> str:
        """生成完整URL(示例:/api/devices/{device_id} -> /api/devices/123)"""
        # 替换路径参数
        formatted_path = base_path
        for param in path_params:
            formatted_path = formatted_path.replace(f"{{{param}}}", f"{{self.faker.uuid4()}}")
        # 拼接基础URL
        return f"{self.base_url}/{formatted_path.lstrip('/')}"

    def _parse_path_params(self, path: str) -> List[str]:
        """解析路径参数"""
        return re.findall(r"{(\w+)}", path)

    def _generate_method_name(self, endpoint: APIEndpoint) -> str:
        """生成测试方法名"""
        clean_path = re.sub(r"[{}]", "", endpoint.path)
        return f"test_{endpoint.method.lower()}_{clean_path.strip('/').replace('/', '_')}"

    def _path_to_method(self, path: str) -> str:
        """路径转方法名"""
        return re.sub(r"\W+", "_", path).strip("_")

    def _save_to_file(self, path: str, content: str):
        """保存测试文件"""
        Path(path).parent.mkdir(parents=True, exist_ok=True)
        with open(path, "w", encoding="utf-8") as f:
            f.write(content)


if __name__ == "__main__":
    # 使用示例
    generator = TestCaseGenerator(
        api_key="your api_key",
        base_url=""
    )

    with open(r"D:\python_test\pythonProject\project\api_docs\你的.json", encoding="utf-8") as f:
        swagger_data = json.load(f)

    generator.generate_test_cases(
        swagger_data=swagger_data,
        output_path=r"D:\python_test\pythonProject\你的存放测试用例地址"
    )
print("✅自动化测试用例已生成!")

备注:目前生成的用例并不能直接调用使用,需要再手动调整脚本

生成的用例,目前未取到json值,这里我再检查优化一下
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2339166.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Tauri2】026——Tauri+Webassembly

前言 不多废话 直言的说,笔者看到这篇文章大佬的文章 【04】Tauri 入门篇 - 集成 WebAssembly - 知乎https://zhuanlan.zhihu.com/p/533025312尝试集成一下WebAssembly,直接开始 正文 准备工作 新建一个项目 安装 vite的rsw插件和rsw pnpm instal…

Notepad++中将文档格式从Windows(CR LF)转换为Unix(LF)

在Windows中用记事本写了一个.sh的Linux运行脚本,是无法直接在Linux中执行,需要首先把文本编码格式转换为Unix的,特别是换行符这些,转换步骤如下: 1、打开文档 在Notepad中打开需要转换的文件。 2、进入文档格式转换…

Linux常见工具如yum、vim、gcc、gdb的基本使用,以及编译过程和动静态链接的区别

目录 一、工具的本质 二、一些常用的工具 1.yum 2.vim 1)vim的三种基本模式: 2)vim的基本操作 ①命令模式下的基本操作: ②插入模式: ③底行模式: 3)vim的配置:让他变得更好用 3.gcc…

RBAC的使用

1、简述RBAC的作用及工作流程 Rbac基于角色访问控制,用于管理用户对集群资源的访问权限,通过定义角色和绑定规则,将用户与权限进行关联,作用:权限精细化管理,操作便捷与统一管理,动态调整权限。…

MySQL+Redis实战教程:从Docker安装部署到自动化备份与数据恢复20250418

MySQLRedis实战教程:从Docker安装部署到自动化备份与数据恢复 一、前言 在企业应用中,对MySQL和Redis运维的要求越来越高: 不能仅是启动就算部署运行稳定、隔离、访问控制、备份恢复、安全可靠,才是 企业级的基本功能 本文将手…

AI驱动商业变革:零售行业的智能化跃迁

引言:AI技术迈入黄金时代 2024年成为生成式AI(Gen AI)全面落地的关键年。据麦肯锡《技术趋势展望》报告,生成式AI相关投资同比增长​7倍​​,其经济价值预计达​​2.6-4.4万亿美元​​[1]。在零售领域,该技…

AI调试工具有哪些?

一、深度学习框架专用调试工具 TensorBoard • 功能:实时监控训练指标(损失值、准确率)、可视化神经网络结构、分析参数分布和梯度信息 • 适用框架:TensorFlow、PyTorch(通过插件) • 特点:支持…

交易模式革新:Eagle Trader APP上线,助力自营交易考试效率提升

近年来,金融行业随着投资者需求的日益多样化,衍生出了众多不同的交易方式。例如,为了帮助新手小白建立交易基础,诞生了各类跟单社区;而与此同时,一种备受瞩目的交易方式 —— 自营交易模式,正吸…

健身会员管理系统(ssh+jsp+mysql8.x)含运行文档

健身会员管理系统(sshjspmysql8.x) 对健身房的健身器材、会员、教练、办卡、会员健身情况进行管理,可根据会员号或器材进行搜索,查看会员健身情况或器材使用情况。

捋一遍Leetcode【hot100】的二叉树专题

二叉树专题 除了后面两个,都挺简单 二叉树的中序遍历 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int …

【测试文档】项目测试文档,测试管理规程,测试计划,测试文档模版,软件测试报告书(Word)

原件获取列表: 系统测试方案-2.docx B-Web安全服务渗透测试模板.docx 压力测试报告.docx安全测试用例及解析.docx 测试计划.doc 测试需求规范.doc 测试需求指南.docx 测试用例设计白皮.doc 单元测试报告模板.doc 单元测试计划模板.doc 回归测试指南.doc 集成测试报…

Linux的联网网络管理攻略

RHEL9版本特点 在RHEL7版本中,同时支持network.service和NetworkManager.service(简称NM)。 在RHEL8上默认只能通过NM进行网络配置,包括动态ip和静态ip,若不开启NM,否则无法使用网络RHEL8依然支持network.service&am…

Linux上位机开发实践(SoC和MCU的差异)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 soc一般是指跑linux的芯片,而mcu默认是跑rtos的芯片,两者在基本原理方面其实差异不大。只不过,前者由于性能的原…

ios app的ipa文件提交最简单的方法

ipa文件是ios的app打包后生成的二级制文件,在上架app store connect或做testflight测试的时候,它提示我们需要使用xcode、transporter或xcode命令行等方式来上传。 而xcode、transporter或xcode命令行的安装都需要使用mac电脑,假如没有mac电…

详细解释浏览器是如何渲染页面的?

渲染流程概述 渲染的目标:将HTML文本转化为可以看到的像素点 当浏览器的网络线程收到 HTML 文档后,会产生一个渲染任务,并将其传递给渲染主线程的消息队列。在事件循环机制的作用下,渲染主线程取出消息队列中的渲染任务&#xff0…

Nacos安装及数据持久化

1.Nacos安装及数据持久化 1.1下载nacos 下载地址:https://nacos.io/download/nacos-server/ 不用安装,直接解压缩即可。 1.2配置文件增加jdk环境和修改单机启动standalone 找到bin目录下的startup.cmd文件,添加以下语句(jdk路径根据自己…

FPGA_YOLO(四)用HLS实现循环展开以及存储模块

Vivado HLS(High-Level Synthesis,高层次综合)是赛灵思(Xilinx)在其 Vivado 设计套件 中提供的一款工具,用于将 高级编程语言(如 C、C、SystemC) 直接转换为 硬件描述语言&#xff0…

ASP.NET MVC 实现增删改查(CRUD)操作的完整示例

提供一个完整的 ASP.NET MVC 实现增删改查(CRUD)操作的示例。该示例使用 SQL Server 数据库,以一个简单的 Product 实体为例。 步骤 1:创建 ASP.NET MVC 项目 首先,在 Visual Studio 中创建一个新的 ASP.NET MVC 项目…

MCP理解笔记及deepseek使用MCP案例介绍

文章目录 一、MCP介绍(1)使用MCP与之前的AI比较(2)原理(3)优点 二、deepseek使用MCP使用案例介绍 一、MCP介绍 全称 模型上下文协议 来源 由Claude母公司Anthropic于24年底开源发布 简介 AI大模型的标准化…

# 手写数字识别:使用PyTorch构建MNIST分类器

手写数字识别:使用PyTorch构建MNIST分类器 在这篇文章中,我将引导你通过使用PyTorch框架构建一个简单的神经网络模型,用于识别MNIST数据集中的手写数字。MNIST数据集是一个经典的机器学习数据集,包含了60,000张训练图像和10,000张…