如何用AI工具编写一个轻量化CRM系统(七):AI生成pytest测试脚本

news/2025/10/4 15:16:39/文章来源:https://www.cnblogs.com/tlnshuju/p/19125618

如何用AI工具编写一个轻量化CRM系统(七):AI生成pytest测试脚本

2025-10-04 15:12  tlnshuju  阅读(0)  评论(0)    收藏  举报

要实现根据Flask接口文档自动生成测试脚本、自动执行多次并汇总结果,可以通过解析Swagger文档+动态生成pytest测试用例+测试结果汇总的流程完成。以下是完整的Python实现方案:

在这里插入图片描述

一、环境准备

  1. 安装依赖库:
    pip install requests pytest pytest-html flasgger
    • requests:发送HTTP请求;
    • pytest:测试框架,支持自动发现和执行测试;
    • pytest-html:生成HTML测试报告;
    • flasgger:Flask的Swagger文档生成库(确保你的Flask应用已集成,用于提供结构化的Swagger JSON)。

二、核心逻辑实现

1. 获取并解析Swagger文档

Flask应用通常通过/swagger.json提供结构化的Swagger文档(需集成flasgger)。我们需要先获取该文档,解析出所有接口的信息(路径、方法、参数、预期响应)。

import requests
from typing import Dict, List, Any
def get_swagger_doc(swagger_url: str) -> Dict[str, Any]:
"""获取Swagger JSON文档"""
response = requests.get(swagger_url)
response.raise_for_status()  # 确保请求成功
return response.json()
def parse_swagger_interfaces(swagger_doc: Dict[str, Any]) -> List[Dict[str, Any]]:
"""解析Swagger文档,提取接口信息(路径、方法、参数、响应)"""
interfaces = []
paths = swagger_doc.get("paths", {})
for path, methods in paths.items():
for method, details in methods.items():
# 仅处理GET/POST/PUT/DELETE方法
if method.lower() in ["get", "post", "put", "delete"]:
interface = {
"path": path,
"method": method.upper(),
"parameters": details.get("parameters", []),  # 接口参数(查询/请求体)
"responses": details.get("responses", {})    # 预期响应
}
interfaces.append(interface)
return interfaces
2. 生成测试用例

根据解析出的接口信息,生成覆盖正常流、异常流、边界条件的测试用例。例如,登录接口的测试用例包括:正常登录、错误用户名、错误密码、缺少参数等。

def generate_test_cases(interfaces: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
"""根据接口信息生成测试用例"""
test_cases = []
for interface in interfaces:
path = interface["path"]
method = interface["method"]
# 1. 登录接口(/login,POST)
if path == "/login" and method == "POST":
test_cases.extend([
{
"name": "login_success",  # 测试用例名称
"request": {"json": {"username": "admin", "password": "password123"}},
"expected": {"status_code": 200, "json": {"access_token": str, "message": "登录成功"}}
},
{
"name": "login_wrong_username",
"request": {"json": {"username": "nonexistent", "password": "password123"}},
"expected": {"status_code": 401, "json": {"message": "用户名或密码错误"}}
},
{
"name": "login_missing_username",
"request": {"json": {"password": "password123"}},
"expected": {"status_code": 400, "json": {"message": "缺少必填字段: username"}}
}
])
# 2. 客户列表接口(/crm/customers,GET)
elif path == "/crm/customers" and method == "GET":
test_cases.extend([
{
"name": "get_customers_success",
"request": {},
"expected": {"status_code": 200, "json": {"customers": list, "pagination": dict}}
},
{
"name": "get_customers_unauthorized",
"request": {},
"expected": {"status_code": 401, "json": {"message": "缺少访问令牌"}}
}
])
# 3. 创建客户接口(/crm/customers,POST)
elif path == "/crm/customers" and method == "POST":
test_cases.extend([
{
"name": "create_customer_success",
"request": {"json": {"name": "李四", "email": "lisi@example.com", "phone": "13900139000"}},
"expected": {"status_code": 201, "json": {"id": int, "name": "李四", "email": "lisi@example.com", "message": "客户创建成功"}}
},
{
"name": "create_customer_missing_name",
"request": {"json": {"email": "lisi@example.com", "phone": "13900139000"}},
"expected": {"status_code": 400, "json": {"message": "缺少必填字段: name"}}
}
])
return test_cases
3. 动态生成pytest测试函数

利用pytest的动态测试生成能力,为每个测试用例生成独立的测试函数,自动发送请求并验证响应。

def generate_test_function(test_case: Dict[str, Any]) -> callable:
"""为单个测试用例生成pytest测试函数"""
def test_func():
# 构造请求URL和方法
method = test_case["request"].get("method", "POST").upper()
path = test_case["path"]
url = f"http://localhost:8000{path}"  # 替换为你的API地址
request_data = test_case["request"]
# 发送HTTP请求
if method == "POST":
response = requests.post(url, json=request_data.get("json", {}))
elif method == "GET":
response = requests.get(url, params=request_data.get("params", {}))
elif method == "PUT":
response = requests.put(url, json=request_data.get("json", {}))
elif method == "DELETE":
response = requests.delete(url, params=request_data.get("params", {}))
else:
raise ValueError(f"不支持的请求方法: {method}")
# 验证1:状态码是否符合预期
expected_status = test_case["expected"]["status_code"]
assert response.status_code == expected_status, \
f"测试用例[{test_case['name']}]失败:预期状态码{expected_status},实际{response.status_code}"
# 验证2:响应体结构和类型是否符合预期
expected_json = test_case["expected"]["json"]
response_json = response.json()
for key, expected_type in expected_json.items():
assert key in response_json, \
f"测试用例[{test_case['name']}]失败:响应缺少字段[{key}]"
assert isinstance(response_json[key], expected_type), \
f"测试用例[{test_case['name']}]失败:字段[{key}]类型错误(预期{expected_type.__name__},实际{type(response_json[key]).__name__})"
return test_func
4. 主程序:注册测试用例并执行

将上述步骤整合,自动生成测试用例、注册测试函数,并通过pytest执行测试,生成HTML报告。

if __name__ == "__main__":
# 1. 配置Swagger文档地址(根据你的Flask应用调整)
SWAGGER_URL = "http://localhost:8000/swagger.json"
try:
# 2. 获取并解析Swagger文档
swagger_doc = get_swagger_doc(SWAGGER_URL)
interfaces = parse_swagger_interfaces(swagger_doc)
print(f"✅ 成功解析到 {len(interfaces)} 个接口")
# 3. 生成测试用例
test_cases = generate_test_cases(interfaces)
print(f"✅ 生成 {len(test_cases)} 个测试用例")
# 4. 动态注册测试函数到pytest
for test_case in test_cases:
test_name = f"test_{test_case['name']}"  # pytest测试函数命名规则
test_func = generate_test_function(test_case)
globals()[test_name] = test_func  # 将测试函数加入全局命名空间
# 5. 执行测试(生成HTML报告)
print("开始运行测试...")
pytest.main([
__file__,          # 当前脚本
"-v",              # 详细模式(显示每个测试用例的结果)
"--html=report.html",  # 生成HTML报告
"--self-contained-html"  # 报告包含所有依赖(无需额外文件)
])
except Exception as e:
print(f"❌ 执行失败:{e}")
exit(1)

三、使用说明

  1. 启动Flask应用:确保你的Flask应用运行在http://localhost:8000,并集成了flasgger(可通过/swagger.json访问Swagger文档)。
  2. 运行测试脚本:执行上述Python脚本:
    python test_crm_api.py
  3. 查看结果
    • 命令行会输出详细的测试结果(通过/失败/错误);
    • 生成report.html文件,打开后可查看测试用例详情失败原因汇总统计(通过率、失败数等)。

四、扩展功能

1. 自动执行多次测试

通过pytest的--count参数指定执行次数(例如执行5次):

pytest.main([
__file__,
"-v",
"--html=report.html",
"--count=5"  # 执行5次测试
])
2. 更灵活的测试数据管理

若测试数据需要复用或参数化,可以使用pytest的@pytest.mark.parametrize装饰器。例如,登录接口的多组用户名/密码:

import pytest
@pytest.mark.parametrize("username, password, expected_message", [
("admin", "password123", "登录成功"),
("nonexistent", "password123", "用户名或密码错误"),
("admin", "wrongpassword", "用户名或密码错误")
])
def test_login_parametrized(username, password, expected_message):
# 发送请求并验证
response = requests.post("http://localhost:8000/login", json={"username": username, "password": password})
assert response.status_code == 200 if "成功" in expected_message else 401
assert expected_message in response.json()["message"]
3. 集成CI/CD

可以将测试脚本集成到CI/CD pipeline(如GitHub Actions、Jenkins),每次代码提交后自动执行测试并生成报告。

总结

该方案通过解析Swagger文档实现测试用例的自动生成,通过pytest动态测试实现自动执行,通过HTML报告实现结果汇总。完全符合“根据接口文档生成测试脚本、自动执行多次、汇总结果”的需求,且支持灵活扩展(如参数化测试、CI/CD集成)。

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

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

相关文章

网站建设总结心得游戏运营备案官方网站

昨天一个客户要在RK3399 Linux开发板上面使用身份证读卡器,由于没有客户的开发板,故只能用本机ubuntu虚拟机来交叉编译,用客户发过来的交叉编译工具,已经编译好libusb然后编译libdonsee.so的时候提示找不到libusb,报错…

实用指南:Linux驱动之V4L2

实用指南:Linux驱动之V4L2pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", …

湖北省建设人力资源网站网页制作素材教学

目录 一、代入排除法 例题 练习 二、数字特性 例题 练习 整除特性 例题 倍数特性 普通倍数 因子倍数 比例倍数 例题 练习 三、方程法 例题 练习 四、 不定方程(组) 例题 练习 一、代入排除法 例题 素数&#xff1a…

儿童与青少年数据安全及体育发展新方向会议

本次会议聚焦儿童和青少年数据安全保护,探讨人工智能对隐私的影响及体育文化在教育中的作用,涵盖数据保护、AI隐私风险等关键技术议题。会议信息 时间:2025年10月10日 地点:克拉科夫布罗尼斯瓦夫捷克体育学院 组织…

做网站运营需要具备什么能力建站公司都有哪些

在Flutter中,异步编程是非常重要的一部分,特别是在处理用户输入、网络请求或其他涉及时间的操作时。Flutter提供了一种强大的工具,称为Stream,用于简化异步编程的过程。 什么是 Stream? Stream是一种用于处理异步数据…

网站等保建设上海好的设计公司

SV-7042T 30W网络对讲广播一体音柱 一、描述 SV-7042T是深圳锐科达电子有限公司的一款壁挂式网络有源音柱,具有10/100M以太网接口,可将网络音源通过自带的功放和喇叭输出播放,其采用防水设计,功率可以从20W到40W。SV-7042T作为网…

Embarcadero Dev-C++ 6.3 中文乱码问题 - 教程

Embarcadero Dev-C++ 6.3 中文乱码问题 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &q…

2025.10.4——2绿

普及/提高- P9869 [NOIP2023] 三值逻辑 图上的问题,听完老师讲解还看了题解才理解。 P3847 [TJOI2007] 调整队形 刚开始用最长公共子序列做,结果是错的。 后来换成区间DP,就过了。

网站建设迁移方案优化官网咨询

支付开宝的本地生活来了!按支付宝财大气粗的做法,它一旦要推什么项目,那自然会在前期疯狂洒钱,以求通过这种模式快速占领市场。 所以,这次支付宝要推本地生活项目,这一贯做法自然得跟上,只是这…

怎么提高自己网站的知名度目前网站开发语言

思维导图 案例一:内在-资产提取-AppinfoScanne AppinfoScanner 一款适用于以 HW 行动/红队/渗透测试团队为场景的移动端(Android、iOS、WEB、H5、静态网站)信息收集扫描工具,可以帮助渗透测试工程师、攻击队成员、红队成员快速收集到移动端或者静态 WEB …

二级域名解析网站专业做网站设计公司价格

在Java并发场景中,会涉及到各种各样的锁,比如:高并发编程系列:4种常用Java线程锁的特点,性能比较、使用场景,这些锁有对应的种类:公平锁,乐观锁,悲观锁等等,这…

十月四日就听《10월 4일》

왠지 요즘에 난 그 소녀가 떠올라 不知为何最近 那女孩总浮现在脑海 내가 숨을 멈출 때 每当我屏住呼吸 就会想起你 너를 떠올리곤 해 在我眼前浮现的 내 눈가엔 아련한 시절의 只有那段朦胧岁月里 너무나 짧았던 太过…

手机浏览器网页加速器360网站推广官网怎么优化

1、BCC异或校验 从输入的HEX第一个字节开始,按字节依次循环计算异或值直到HEX结尾字节,得到的最终一个字节值。 2、C程序 /******************************************************************************* _____ ___ ____ ___ _____ _ …

windows上的实用小软件

来源:https://www.zhihu.com/question/22052999/answer/19519439768788588421、PowerToys(微软官方的工具) 这个绝对是被低估的软件,大部分人根本不知道他的强大,这是微软亲儿子工具集。 很多人一听是微软出的工具…

微博登录网站开发哈尔滨网页制作教程

无限流量手机服务器 内容精选换一换云手机作为一种新型服务,依靠华为云的服务器底座、创新技术及周边服务的天然优势,让移动应用不但可以在物理手机运行,还可以在云端智能运行。相比常见的手机模拟方案,云手机在性能、兼容性、稳定…

algorithm B manipulations 1/99

step by step for the Huffman algorithm in C++, writing down every action on each data structure and labeling it as Insert / Update / Remove / Combine / Traverse. This will show exactly how manipulation…

深入解析:Java JVM --- JVM内存区域划分,类加载,GC垃圾回收

深入解析:Java JVM --- JVM内存区域划分,类加载,GC垃圾回收pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Con…

天津宇昊建设集团有限公司网站济南专业网站建设咨询

二叉搜索树中第K小的元素 二叉搜索树具有如下性质: 结点的左子树只包含小于当前结点的数。 结点的右子树只包含大于当前结点的数。 所有左子树和右子树自身必须也是二叉搜索树。 二叉树的中序遍历即按照访问左子树——根结点——右子树的方式遍历二叉树&#x…

比赛题2

DMY DAY5 T1 糖丸了,建个分层图第二层连边权为 \(0\) 的边,跑 01bfs 即可,时间复杂度 \(\mathcal{O}(n + m + V \log V)\)。点击查看代码 #include <bits/stdc++.h> using namespace std; const int N = 2e5 …

【微科普】蒙特卡洛(全网最好懂,附MATLAB算法):用 “撒芝麻” 的智慧破解复杂挑战 —— 从披萨面积到金融风险的诗意算法

【微科普】蒙特卡洛(全网最好懂,附MATLAB算法):用 “撒芝麻” 的智慧破解复杂挑战 —— 从披萨面积到金融风险的诗意算法2025-10-04 14:42 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !import…