当下的AI技术迅猛渗透到各领域,对软件测试也造成不小的冲击。对测试从业者而言,无需畏惧 AI 的冲击,更应聚焦自身核心能力的提升。
以下分享了如何利用AI(通义大模型),将日常需求转化为测试用例,并自动生成到AgileTC测试用例管理平台中。
(一)核心思路
1、调用AI生成测试用例
用户输入PRD文本 → 构造Prompt → 调用DashScope API → 获取AI返回的JSON
python
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)
python
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() 解析 → 字典列表 ListDict
python
# 提取模型返回的文本
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截取) |
python
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
}
python
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接口导入
python
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思维导图格式,实现从需求到用例的一键生成。