目录[-]
一、前言:如果公司要求你用AI生成测试用例,你会怎么做?
这是我们系列教程的第五节了, 自从2025年开始,AI大模型的热度越来越高,各种工具层出不穷,AI非常智能,可以生成我们平时忽略掉的问题,质量好、效率高,那么,真的适合我们的业务吗?
我尝试过,在本地搭建一个Ollama环境,使用qwen2.5:7b模型,将公司(内网环境与外网隔离)的产品文档,直接扔给AI,AI给出的内容,漏洞百出,那么是AI错了吗?
当然不是,是“喂”的方式不对。
我们换个思路想一想,产品提供的文档,大多数是 docx 格式的,当我们直接将 docx 格式的产品文档扔给AI,AI会怎么做?
AI的步骤:
-
识别文件类型:确保确实是 docx 格式的内容,不是图片或是其他格式
- 安全性检查:确保不含违规、恶意内容
- 把文档“读成纯文本”:
- 将文档中的“正文”、“标题”、“段落”、“列表”等信息,全部提取出来,转成文字格式。
- 如果有文字的“图片”,先做 ORC 识别,提取图里的文字再理解内容;
- 如果是没有文字的“图片”,也能理解和分析。
- 理解你让我“分析什么,生成什么”
- 是总结?
- 是提取要点?
- 是找问题?
- 是润色?
- 是做表格?
- 等等,明确用户的“任务目标”。
- 对文本做理解与处理
- 分段理解语义
- 识别逻辑关系
- 抓重点、去冗余(相当于看懂整篇文章说了什么)
- 按要求生成结果
- 要总结——》生成:精简总结
- 要提取信息——》生成:要点
- 要改写代码——》重新修改
- 最后将结果以“流式输出”的方式返回给用户
结论就是:
-
直接将产品文档扔给AI的做法不可取,AI可能理解一部分,但绝不可能全部理解。
- 产品设计文档的能力与产品息息相关,如果产品设计文档本身就不完善、不准确,怎么保证AI设计准确?
- 业务关联性与复杂度,如果一个功能,与其他功能关联,或需要结合其他页面判断,AI能明白么?
- 综上所述,我们在设计之前,需要弄明白,什么是AI可以做的,什么是AI做不到的。
我们公司采用的策略是:
测试左移 —— 在收到产品设计文档后,测试对其再次加工,加工为AI模型最能读懂的方式 ,YAML 格式的PRD 文档。它是最适合AI大模型理解的类型。
二、核心思路说明
2.1 第一阶段:直接将 PRD(产品设计文档)给 AI大模型
把产品经理给的 docx 文档直接扔给 AI 大模型,prompt 写明“帮我生成测试用例”。
结果:
-
AI 理解不准确,漏测、胡编乱造
- 生成结果不稳定
- 边界场景覆盖率低
问题分析:
-
docx图文混排,AI看到的是文本流,不知道哪个是标题、哪个是字段、哪个是约束条件。
2.2 第二阶段:人工整理后再喂
测试人员看一遍 PRD ,完全理解后,将关键信息整理成文本再给 AI。
结果:
-
质量提升
- 整理工作耗时,每个人整理标准不一致
- 需求变更时,需要重新整理
问题分析:
-
输入的结构化不足,一个团队里,每个人整理的水平不一,生成的用例也就不一。
2.3 第三阶段:测试左移 + YAML 结构化
请注意上面步骤的第3点,AI最擅长识别的是“纯文本”,本质上是“输入质量决定了输出质量”,如果输入不稳定,AI返回的值肯定也会不稳定。所以,我们公司将“独立、边界清晰、逻辑确定”的业务模块和功能,主动拆分 YAML 格式的文档,并将其结构化。
三、YAML 字段设计:让AI理解你的真实意图
YAML 是什么?它是一种“人机都容易理解”的数据格式,可以理解为一个大 JSON。一个更好写、更易读、长的像散文的 JSON 格式,如下:
3.1 基础版本:定义规则
# yaml
- name: 手机号输入框
type: input
required: true
placeholder: "请输入手机号码"
max_length: 11
allowed: numeric
这个 YAML 告诉AI:
- 这是一个输入框,必填
- 最多11位,只能输入纯数字
- 提示文字是“请输入手机号码”
AI 看到后,就知道要生成:
- 手机输入框为“空”校验用例
- 12位超过长度的校验用例
- 输入非数字的异常用例
3.2 进阶版本:内置测试数据
# yaml
- name: 手机号输入框
type: input
required: true
placeholder: "请输入手机号码"
min_length: 11
max_length: 11
allowed: numeric # 只允许输入纯数字
rules:
- 必须是11位纯数字
- 不允许小于11位 或 大于11位
valid_examples:
- 13800001111
invalid_examples:
- 123456(位数不足)
- 13800000000000(位数超长)
- 133-5555_3134(空格 或 横杠等特殊字符)
这样一来,AI就能精准生成:
- 正向用例:输入 13800000111——》登录成功
- 反向用例:小于11位、大于11位、非数字、空——》提示错误
3.3 再次进化版本:添加更多规则
# yaml
- name: 手机号输入框
type: input
required: true
placeholder: "请输入手机号码"
min_length: 11
max_length: 11
allowed: numeric # 只允许输入纯数字
rules:
- 必须是11位纯数字
- 不允许小于11位 或 大于11位
valid_examples:
- 13800001111
invalid_examples:
- 123456(位数不足)
- 13800000000000(位数超长)
- 133-5555_3134(空格 或 横杠等特殊字符)
error_message:
length_error:"请输入11位手机号码"
requied_error:"手机号不能为空"
# 测试覆盖类型(AI 自动生成用例)
test_coverage:
- 空值校验
- 长度校验
- 格式校验
- 号段合法性校验
- 黑名单校验
- 特殊字符校验
- 连续/重复数字校验
结论:设计一套完整、精确的结构化 PRD,提升是巨大的。在设计好 YAML 之后,我们就可以开始编写代码了。
四、核心代码实现
4.1 为什么不用 ChromaDB?
一开始我打算使用 ChromaDB,但在 Windows环境下,其稳定性堪忧,频繁崩溃,报错代码:0xC000005,分析后发现是 sqlite3 线程问题,尝试修复但没有成功。
最后我选择“字典模式”+“FAISS”的方案:
- 保留原始 YAML 字典,用于精确字段访问
- 减轻 prompt 修改难度(字典格式字段比文本块更容易读取)
- 将字典转换为文本块,存入 FAISS 做语义检索
4.2 核心代码
import yaml
import json
import os
import pandas as pd
from langchain_community.embeddings import OllamaEmbeddings
from langchain_community.vectorstores import FAISS
print("🚀 字典模式 + FAISS版")
# ========== 1. 加载YAML为字典 ==========
with open('product.yaml', 'r', encoding='utf-8') as f:
spec_dict = yaml.safe_load(f)
print(f"📄 第1步:加载完成,模块数: {len(spec_dict.get('modules', []))}")
# ========== 2. 字典转文本块(用于FAISS检索)==========
def dict_to_texts(obj, path="", texts=None):
"""保留字典结构信息,转换为文本块"""
if texts is None:
texts = []
if isinstance(obj, dict):
for k, v in obj.items():
new_path = f"{path}.{k}" if path else k
dict_to_texts(v, new_path, texts)
elif isinstance(obj, list):
for i, item in enumerate(obj):
dict_to_texts(item, f"{path}[{i}]", texts)
else:
texts.append(f"{path}: {obj}")
return texts
texts = dict_to_texts(spec_dict)
print(f"📚 第2步:生成 {len(texts)} 个文本块")
# print(texts)
# ========== 3. 创建或加载FAISS ==========
embeddings = OllamaEmbeddings(model="nomic-embed-text")
# 检查是否已有向量库
if os.path.exists("./faiss_db") and os.path.isdir("./faiss_db"):
print("📂 检测到已有FAISS库,直接加载...")
vectorstore = FAISS.load_local("./faiss_db", embeddings, allow_dangerous_deserialization=True)
print("✅ FAISS加载完成")
else:
print(f"🔄 未找到FAISS库,开始生成向量... (共{len(texts)}个文本块)")
print(" ⏳ 每个向量约1-3秒,请耐心等待...")
from tqdm import tqdm
batch_size = 10
all_embeddings = []
for i in tqdm(range(0, len(texts), batch_size), desc="生成向量"):
batch = texts[i:i + batch_size]
batch_embeddings = embeddings.embed_documents(batch)
all_embeddings.extend(batch_embeddings)
print("🔄 创建FAISS索引...")
vectorstore = FAISS.from_embeddings(
text_embeddings=list(zip(texts, all_embeddings)),
embedding=embeddings
)
print("💾 保存FAISS索引...")
vectorstore.save_local("./faiss_db")
print("✅ FAISS保存完成")
# ========== 4. 获取字段字典(不需要检索)==========
try:
list_all = spec_dict.get('modules', [])
if not list_all:
raise ValueError("未找到任何模块")
# 获取第一个模块的所有字段
fields_list = list_all[0].get('fields', [])
if not fields_list:
raise ValueError("模块中没有字段定义")
print(f"📋 第4步:成功获取{len(fields_list)}个字段")
for field in fields_list:
print(f" - {field.get('name')} ({field.get('type')})")
except Exception as e:
print(f'❌ 第4步出错: {e}')
exit()
4.3 流失输出:告别等待焦虑
answer = ""
for chunk in llm.stream(prompt):
print(chunk, end="", flush=True)
answer += chunk
llm.stream():这个方法就会以“流式输出”的格式,就像是在和AI对话一样,生成结果存在xlsx文件后,如下
4.4 prompt 规则优化
上面的代码可以明显看到,【生成规则】写了几个,如:1. required: true → 生成“为空校验”用例。
但是我总不可能每次都修改源代码,就为了适应“新规则”吧,所以,我们需要将想要AI读取的规则,提前写到 YAML 里,如下:
# yaml
ai_test_case_rules:
- 规则1:required: true → 必须生成【为空校验】用例
- 规则2:min_length、max_length 存在 → 必须生成【边界值用例】:等于长度成功、小于长度失败、大于长度失败
- 规则3:allowed: numeric → 必须生成【非数字校验用例】:包含字母、汉字、特殊符号、空格、分隔符均不通过
- 规则4:每个字段必须覆盖三类用例:正常值、边界值、异常值
- 规则5:invalid_examples 中每一项 → 必须生成一条对应失败用例
- 规则6:valid_examples 中每一项 → 必须生成一条对应成功用例
- 规则7:rules 中每一条校验规则 → 必须生成对应的正向/反向用例
- 规则8:所有 error_message 必须匹配对应用例的预期结果
- 规则9:test_coverage 列表中每一项 → 必须生成对应测试场景用例
在 Python 里,添加规则如下(第6条)
最后生成的结果就变成下面这样,从4条用例,变成8条用例,那么还可不可以继续优化?当然可以,只是本文不再套娃了。
五、总结与展望
5.1 核心收获
- AI 的输入质量决定输出质量:不要让 AI 猜,而是主动结构化。
- 测试左移不只是早点接入测试:而是用结构化的方式把需求变成可执行的测试重点。
- FAISS 比 ChromaDB稳定:在Windows环境更推荐。
5.2 适用场景
这套方案适合:
- 独立、边界清晰、逻辑确定的业务模块(如配置项管理、登录、基础信息维护等)
- 表单类、输入校验类功能
- 需要频繁回归的场景
- 简单的测试功能
复杂场景(如交易主流程、支付回调、订单状态机)目前还不推荐 AI 化,因为“喂”给AI的成本太高了。
5.3 下一步计划
现在我们的设计,还是比较简单的,要知道,AI 优化是永无止境的,设计和推广 YAML 是时代进步的一个缩影,我们设想,我使用了AI在本地环境搭建了一套完善的“AI 生成测试用例”方法,新手可以专注于基础的业务功能测试,而老手就可以专注于“支付、订单”等更关键的业务,这,就是AI的价值所在。
AI 不会取代测试工程师,就像屠龙刀,三岁小孩子使用和谢逊使用,自然是天壤之别,外功固然重要,但测试工程师的内功也不能放下。
to be continued 。。。