当前位置: 首页 > news >正文

基于AI大模型,将自然语言需求自动转化为结构化测试用例

当下的AI技术迅猛渗透到各领域,对软件测试也造成不小的冲击。对测试从业者而言,无需畏惧 AI 的冲击,更应聚焦自身核心能力的提升。

以下分享了如何利用AI(通义大模型),将日常需求转化为测试用例,并自动生成到AgileTC测试用例管理平台中。

(一)核心思路

1、调用AI生成测试用例

用户输入PRD文本 → 构造Prompt → 调用DashScope API → 获取AI返回的JSON

prd_text = input("请输入需求描述: ").strip() ai_generator = QwenAIGenerator(api_key="") #通义api的key raw_test_cases = ai_generator.generate_from_prd(prd_text) print("AI返回的json:",raw_test_cases)
class QwenAIGenerator: """使用通义千问API生成测试用例""" def __init__(self, api_key: str): self.api_key = api_key dashscope.api_key = api_key def generate_from_prd(self, prd_text: str) -> List[TestCase]: """ 通过通义千问API生成测试用例 要求模型返回严格的JSON格式,便于解析 """ prompt = f""" 你是一个资深测试工程师。请根据以下需求文档(PRD)内容,生成测试用例。 需求内容: {prd_text} 请严格按照以下JSON格式输出,不要包含任何其他解释或文本,只输出json数组: [ {{ "title": "用例标题", "steps": "步骤1\n步骤2", "expected": "结果1\n结果2", "precondition": "前置条件", "priority": "P0", "module": "所属模块", "tags": ["标签1", "标签2"] }} ] """ try: # 调用通义千问API response = dashscope.Generation.call( model='qwen-plus', prompt=prompt, temperature=0.5 ) # 提取模型返回的文本 content = response.output['text'] print(f"🤖 AI原始返回: {content}") # 调试用:打印AI返回的原始内容 except Exception as e: print(f"❌ 解析或调用异常: {e}") return []

2、解析AI返回结果

AI返回的JSON字符串 → json.loads() 解析 → 字典列表 List[Dict]

# 提取模型返回的文本 if response.status_code == 200: content = response.output['text'] print(f"🤖 AI原始返回: {content}") # 调试用:打印AI返回的原始内容 # 清洗AI返回内容,提取JSON部分 content = self._extract_json(content) # 尝试解析JSON case_dicts = json.loads(content) # 确保每个字典的字段完整 for case_dict in case_dicts: case_dict.setdefault("title", "未命名用例") case_dict.setdefault("steps", "") case_dict.setdefault("expected", "") case_dict.setdefault("precondition", "") case_dict.setdefault("priority", "P2") case_dict.setdefault("module", "默认模块") # 确保tags是列表 tags = case_dict.get("tags", []) if isinstance(tags, str): case_dict["tags"] = [tags] return case_dicts else: print(f"❌ API调用失败: {response.message}") return [] def _extract_json(self, text: str) -> str: """ 从AI返回的文本中提取纯JSON内容 AI可能会返回 ```json [...] ``` 这样的格式 """ import re # 尝试匹配 ```json ... ``` 代码块 match = re.search(r'```(?:json)?\s*\n?(.*?)\n?\s*```', text, re.DOTALL) if match: return match.group(1).strip() # 尝试匹配纯JSON数组 match = re.search(r'(\[.*\])', text, re.DOTALL) if match: return match.group(1).strip() # 都没有匹配到,返回原文 return text.strip()

3、转换为AgileTC思维导图格式

字典列表 → 构建思维导图树 → 输出AgileTC格式的JSON字符串

方法作用
build_case_content(test_points)主入口,遍历测试点列表,构建完整的思维导图树
_create_text_node(label, text)创建叶子节点,如"标签: 冒烟测试"
_create_list_node(label, text)创建带子节点的父节点,按换行符拆分,每行一个子节点
_generate_id()为每个节点生成唯一ID(UUID截取)
class MindMapBuilder: """构建AgileTC需要的思维导图格式""" def build_case_content(self, test_points: List[Dict]) -> str: """ 构建思维导图格式的caseContent test_points: 包含多个测试点的列表,每个测试点是一个字典 """ # 构建完整的思维导图结构 mindmap = { "root": { "data": { "id": self._generate_id(), "created": int(time.time() * 1000), "text": test_points[0].get("module", "测试用例") # 中心主题使用模块名或默认名 }, "children": self._build_all_children(test_points) }, "template": "default", "theme": "fresh-blue", "version": "1.4.43", "base": 0 } return json.dumps(mindmap, ensure_ascii=False) def _build_all_children(self, test_points: List[Dict]) -> List[Dict]: """ 构建所有测试点的子节点 每个测试点作为一个大的分支(父节点),下面包含步骤和预期 """ children = [] for point in test_points: # 1. 创建测试点分支(父节点) point_node = { "data": { "id": self._generate_id(), "created": int(time.time() * 1000), "text": f"【{point.get('priority', 'P2')}】{point.get('title', '无标题')}" }, "children": [] } # 2. 添加步骤子节点 if point.get("steps"): steps_node = self._create_list_node("执行步骤", point["steps"]) point_node["children"].append(steps_node) # 3. 添加预期子节点 if point.get("expected"): expected_node = self._create_list_node("预期结果", point["expected"]) point_node["children"].append(expected_node) # 4. 添加标签(如果需要) if point.get("tags"): tags_node = self._create_text_node("标签", ", ".join(point["tags"])) point_node["children"].append(tags_node) children.append(point_node) return children def _generate_id(self) -> str: """ 生成唯一节点ID AgileTC使用类似UUID的格式作为节点标识 """ return str(uuid.uuid4()).replace("-", "")[:20] def _create_text_node(self, label: str, text: str) -> dict: """ 创建单个文本节点 用于展示标签、前置条件等单行文本信息 生成的结构示例: 标签: 冒烟测试, 登录模块 """ return { "data": { "id": self._generate_id(), "created": int(time.time() * 1000), "text": f"{label}: {text}" }, "children": [] } def _create_list_node(self, label: str, text: str) -> dict: """ 创建列表节点(带子节点) 用于展示步骤、预期结果等多行信息 每一行变成一个子节点 生成的结构示例: 执行步骤 ├── 1. 打开登录页面 ├── 2. 输入手机号 └── 3. 点击获取验证码 """ # 按换行符拆分,过滤空行 lines = [line.strip() for line in text.split("\n") if line.strip()] # 构建子节点列表 children = [] for line in lines: children.append({ "data": { "id": self._generate_id(), "created": int(time.time() * 1000), "text": line }, "children": [] }) # 返回带子节点的父节点 return { "data": { "id": self._generate_id(), "created": int(time.time() * 1000), "text": label }, "children": children }
mindmap_builder = MindMapBuilder() case_data = { "productLineId": AGILETC_CONFIG["productLineId"], "channel": AGILETC_CONFIG["channel"], "creator": AGILETC_CONFIG["username"], "caseType": 1, # 用例标题可以取第一个用例的标题,或者自定义 "title": f"综合测试用例:{raw_test_cases[0].get('module', '功能测试')}", "description": f"该用例包含 {len(raw_test_cases)} 个测试点", # 🔴 关键:将所有测试点传入 builder "caseContent": mindmap_builder.build_case_content(raw_test_cases), "priority": 1, "status": 1, "folderId": 1, "module": raw_test_cases[0].get("module", "默认模块"), "tags": "AI生成,综合用例", "createTime": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "updateTime": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "projectId": AGILETC_CONFIG["project_id"], "autoStatus": 0, "reviewStatus": 0, "version": "1.0", "bizId": AGILETC_CONFIG["bizId"], "creator": AGILETC_CONFIG["creator"], "productLineId": AGILETC_CONFIG["productLineId"] }

4、对接测试用例平台

AgileTC格式JSON → 写入文件 / 调用AgileTC接口导入

AGILETC_CONFIG = { "base_url": "https://testacthuyitool.jidiandian.cn", "username": "", # 你的用户名 "bizId": "-1", # 默认文件夹ID "project_id": 1, "channel": 1, "caseType": 0, "creator": "", "productLineId": 1 } class AgileTCClient: def __init__(self, config: Dict): self.base_url = config["base_url"].rstrip('/') self.username = config["username"] self.bizId = config["bizId"] self.project_id = config["project_id"] self.channel = config["channel"] self.caseType = config["caseType"] self.creator = config["creator"] self.productLineId = config["productLineId"] self.session = requests.Session() self.session.cookies.set('username', self.username) self.headers = { "User-Agent": "Mozilla/5.0", "Content-Type": "application/json;charset=UTF-8", "Accept": "application/json, text/plain, */*", } def create_test_case(self, case_data: Dict) -> Dict: """创建测试用例 - 针对你的API响应格式修复""" url = f"{self.base_url}/api/case/create" print(f"📤 创建用例: {case_data.get('title')}") try: response = self.session.post(url, json=case_data, headers=self.headers, timeout=10) print(f"📡 响应状态码: {response.status_code}") print(f"📡 响应内容: {response.text[:200]}...") # 解析JSON响应 result = response.json() print(f"📡 解析后的JSON: {result}") # 🔴 关键修复:正确处理data字段 if result.get("code") == 200: data_value = result.get("data") # 检查data的类型 if isinstance(data_value, dict): # data是字典,包含id字段 case_id = data_value.get("id", "未知") print(f"✅ 创建成功!用例ID: {case_id}") elif isinstance(data_value, (int, str)): # data是整数或字符串,直接就是用例ID case_id = data_value print(f"✅ 创建成功!用例ID: {case_id}") else: # 其他类型 case_id = "未知" print(f"✅ 创建成功!data字段: {data_value}") return { "success": True, "code": 200, "msg": result.get("msg", "成功"), "data": {"id": case_id} if not isinstance(data_value, dict) else data_value, "raw_response": result } else: error_msg = result.get("msg", f"错误码: {result.get('code')}") print(f"❌ 创建失败: {error_msg}") return { "success": False, "code": result.get("code"), "msg": error_msg, "error": error_msg } except Exception as e: print(f"💥 请求异常: {e}") return {"success": False, "error": str(e)} client = AgileTCClient(AGILETC_CONFIG) result = client.create_test_case(case_data) if result.get("success"): print(f"✅ 所有测试点已合并创建成功!") else: print(f"❌ 创建失败")

(二)注意点

模型名称定位说明
qwen-max旗舰效果最好,最贵
qwen-plus均衡效果和成本平衡,推荐
qwen-turbo快速速度快,成本低

博主一开始用的qwen-max效果最好但贵,很快就账号欠费了,后来换成qwen-plus性价比更高,生成测试用例完全够用。

(三)运行效果

总结:用AI大模型把自然语言的需求文档,自动转成结构化的测试用例,再转换成AgileTC思维导图格式,实现从需求到用例的一键生成。

http://www.jsqmd.com/news/1139381/

相关文章:

  • 【K8s第二篇】生产核心资源精讲:YAML手写+私有镜像仓库+探针+配置热更新(零基础Docker迁移)
  • 中空板生产线厂家哪家好?推荐大连欣科
  • 2026在线本地视频去水印教程:免费无水印导出工具与风险解析
  • 计算机毕业设计之基于SSM的校园在线点餐与配送平台的设计与实现
  • 2026净气型试剂柜服务水平对比:5项核心指标实测指南
  • AI动态叙事技术解析:从有限状态机到LLM的游戏革命
  • Linux理解Shell学习实操笔记
  • Tomcat组件管理源码详解 _
  • Unity ML-Agents强化学习实战:从零训练足球AI智能体
  • 怎么读论文-->部分内容来源:B站UP主 送懒洋洋上学
  • 0x04 VICE
  • 国产飞腾主板 EMC 与热设计实战:从原理图到Layout的10个关键检查点
  • OSCAR骨架条件化世界模型:跨形态机器人通用认知架构
  • 攻击事件:发生在默克尔山上的验证绕过
  • YOLOv8 C++部署实战:基于ONNXRuntime与OpenCV的完整环境配置与推理实现
  • 开源AI模型本地部署实战:从原理到生产环境最佳实践
  • Fable 5被网友薅出省钱神招!最高减70%!
  • PyTorch 2.5 Tensor GPU 初始化:3种方法对比与 2 倍性能提升实测
  • MD文件应用Typora激活
  • Flash 存储单元原理深度解析:从 SLC 到 QLC 的 4 种技术演进与性能影响
  • 高性能跨平台镜像烧录架构设计:解决数据完整性与系统安全的双重挑战
  • ForesightFlow:面向工业动作决策的流匹配架构
  • OpenClaw(小龙虾 AI)本地部署
  • 儿童血小板增多症的病因、诊断与治疗策略
  • 从需求到交付,软件定制开发的全流程管理决定项目成败
  • Python 与 C++ 中 long double 精度不一致的根本原因解析
  • AI Agent 安全:当“操作”取代“对话”,攻击面正在发生结构性转移
  • PyTorch 2.0 MultiHeadAttention 模块实战:3种掩码机制与注意力权重可视化
  • 山路弯道的灯光使用技巧
  • AI写小说+GLM 5.2极限评测:320万字/1000章长篇实战,外部记忆+1M上下文能否做到零崩坏?