【AI测试系统】第2篇:拒绝盲目 AI:规则引擎 10ms 自动生成 36 条测试用例实战(附源码)

AI测试系统系列会写28篇,这是第2篇,会持续更新

先说个反直觉的事:规则引擎比 AI 更适合作为用例生成的第一步

很多人一听"AI测试"就以为所有用例都是大模型生成的。实际上我们跑下来的经验是:规则引擎出基础用例,AI 做精细打磨,两者配合效率最高

原因很简单。规则引擎纯 Python 执行,10 毫秒级出几十条用例,成本为零,结构统一,适合快速评估测试工作量;AI 生成一条用例要 1-3 秒,成本几分钱,但能覆盖规则引擎想不到的边缘场景。先规则后 AI,相当于先用粗筛网捞一遍,再用精筛网补漏。

这篇先讲粗筛网------规则引擎怎么从需求文档名称自动提取功能点,每个功能点生成 3 个测试场景。


一、核心思路:关键词匹配 + 场景模板

规则引擎的输入是需求文档名称(比如"电商秒杀查询功能需求文档"),输出是测试用例列表。中间经过三步:

  1. 从文档名称提取功能点------匹配关键词,找到要测哪些功能
  2. 按功能点名称去重------合并重复项,保留唯一功能点
  3. 为每个功能点生成 3 个场景------正常流程、异常处理、边界条件

整个过程不依赖任何外部 API,纯 Python 代码,毫秒级完成。


二、功能点提取:从文档名称到功能列表

代码里维护了一个 feature_map,把业务关键词映射到功能点:

arduino 复制代码
feature_map = {
    '登录': [
        {'name': '正常登录', 'module': '登录模块', 'priority': 'P0'},
        {'name': '错误密码处理', 'module': '登录模块', 'priority': 'P1'},
        {'name': '账号锁定机制', 'module': '登录模块', 'priority': 'P1'},
        {'name': '忘记密码流程', 'module': '登录模块', 'priority': 'P2'},
    ],
    '订单': [
        {'name': '创建订单', 'module': '订单模块', 'priority': 'P0'},
        {'name': '订单取消', 'module': '订单模块', 'priority': 'P1'},
        {'name': '订单查询', 'module': '订单模块', 'priority': 'P2'},
        {'name': '订单修改', 'module': '订单模块', 'priority': 'P2'},
    ],
    '查询': [
        {'name': '商品列表查询', 'module': '商品查询', 'priority': 'P0'},
        {'name': '秒杀活动查询', 'module': '秒杀查询', 'priority': 'P0'},
        {'name': '订单列表查询', 'module': '订单查询', 'priority': 'P0'},
        # ... 共 12 个查询相关功能点
    ],
    # 还有 '支付'、'商品'、'用户'、'电商'、'秒杀'、'财务' 等关键词(共 10 个)
}

匹配逻辑是按优先级顺序遍历关键词列表:

css 复制代码
priority_keywords = ['查询', '电商', '秒杀', '财务', '商品', '订单', '支付', '用户', '登录']

for keyword in priority_keywords:
    if keyword in base_name:  # base_name = doc_name.lower(),兼容英文文档名
        matched_features.extend(feature_map.get(keyword, []))

为什么要排优先级?因为一个文档名称可能匹配多个关键词。比如"电商秒杀查询需求"同时命中"查询"、"电商"、"秒杀"三个关键词。按优先级顺序匹配,确保更具体的关键词优先被选中。

去重逻辑(关键一步):

ini 复制代码
# 按功能点名称去重,保留第一次出现的优先级
seen = set()
unique_features = []
for f in matched_features:
    if f['name'] not in seen:
        seen.add(f['name'])
        unique_features.append(f)
matched_features = unique_features

如果所有关键词都没命中,兜底策略上场:

ini 复制代码
if not matched_features:
    if '需求' in doc_name:
        matched_features = [
            {'name': '功能完整性测试', 'module': '需求验证', 'priority': 'P0'},
            {'name': '业务流程测试', 'module': '需求验证', 'priority': 'P0'},
            {'name': '异常场景测试', 'module': '需求验证', 'priority': 'P1'},
            {'name': '边界条件测试', 'module': '需求验证', 'priority': 'P2'},
        ]
    else:
        matched_features = [
            {'name': '核心功能流程', 'module': '核心模块', 'priority': 'P0'},
            {'name': '异常处理流程', 'module': '核心模块', 'priority': 'P1'},
            {'name': '边界条件测试', 'module': '核心模块', 'priority': 'P2'},
            {'name': '用户体验测试', 'module': '核心模块', 'priority': 'P3'},
        ]

三、场景模板:每个功能点生成 3 条用例

拿到功能点列表后,为每个功能点套用 3 个场景模板:

ini 复制代码
test_scenarios = [
    {
        'suffix': '正常流程',
        'type': '功能测试',
        'preconditions': '用户已登录且权限充足',
        'steps': ['进入功能页面', '执行正常操作流程', '填写必要的输入信息', '提交操作', '验证系统响应'],
        'expected': '系统正确处理请求并返回预期结果'
    },
    {
        'suffix': '异常处理',
        'type': '异常测试',
        'preconditions': '用户已登录',
        'steps': ['进入功能页面', '输入无效的测试数据', '执行操作', '观察系统错误处理', '验证错误提示'],
        'expected': '系统正确捕获异常并显示友好的错误提示'
    },
    {
        'suffix': '边界条件',
        'type': '边界测试',
        'preconditions': '用户已登录',
        'steps': ['进入功能页面', '输入边界值数据(最大值/最小值)', '执行操作', '验证系统处理结果'],
        'expected': '系统正确处理边界值,不出现崩溃或数据错误'
    }
]

正常流程验证系统"能做对",异常处理验证系统"能容错",边界条件验证系统"能扛住"。三个场景覆盖软件测试最核心的三个维度。

每个功能点 × 3 个场景 = 最终用例数。比如「电商秒杀查询需求」匹配到 20 个功能点(含重复),按名称去重后为 12 个,12 × 3 = 36 条用例。


四、实战走一遍

输入文档名称:"电商秒杀查询功能需求文档"

匹配结果

  • '查询' → 12 个查询相关功能点
  • '电商' → 4 个电商相关功能点
  • '秒杀' → 4 个秒杀相关功能点
  • 去重后共 12 个功能点

生成用例(前 6 条 + 最后 3 条):

编号 名称 模块 优先级 类型
TC001 商品列表查询 - 正常流程 商品查询 P0 功能测试
TC002 商品列表查询 - 异常处理 商品查询 P0 异常测试
TC003 商品列表查询 - 边界条件 商品查询 P0 边界测试
TC004 秒杀活动列表查询 - 正常流程 秒杀查询 P0 功能测试
TC005 秒杀活动列表查询 - 异常处理 秒杀查询 P0 异常测试
TC006 秒杀活动列表查询 - 边界条件 秒杀查询 P0 边界测试
... ... ... ... ...
TC034 边界条件测试 - 正常流程 通用查询 P2 功能测试
TC035 边界条件测试 - 异常处理 通用查询 P2 异常测试
TC036 边界条件测试 - 边界条件 通用查询 P2 边界测试

12 个功能点 × 3 个场景 = 36 条用例,纯 Python 执行,无需调用任何外部 API。


五、规则引擎 vs AI 生成:对比一览

维度 规则引擎 AI 生成
生成速度 10 毫秒级 1-3 秒/条
成本 零(纯本地) 几分钱/条(API 调用)
用例数量 固定(功能点数 × 3) 灵活(可指定数量)
用例质量 结构化但通用 针对性强、更具体
覆盖范围 仅预定义关键词 可理解任意业务场景
可维护性 需手动维护 feature_map 只需改 Prompt
适用场景 快速评估、批量初筛 精细打磨、边缘场景

结论:两者不是替代关系,而是互补关系。规则引擎负责"广度",AI 负责"深度"。


六、踩过的坑

坑 1:功能点重复。「电商秒杀查询」同时命中三个关键词,同一个功能点被添加了多次(比如「订单查询」同时出现在「订单」和「查询」的映射里)。加上按名称去重逻辑后解决。

坑 2:关键词不够用。项目初期只有 9 个关键词,后来接了「物流」、「营销」、「客服」等新模块,feature_map 从 9 个扩展到了 10 个。规则引擎的通病------维护成本随业务增长而上升。

坑 3:优先级分配不够细。P0 全给了核心功能,但实际测试中 P0 用例太多(占了 40%),资源分配不过来。后来调整了策略,把部分 P0 降为 P1,让 P0 只保留真正核心的流程。


七、工程建议

如果你要在自己的项目里落地类似的规则引擎,以下几点经验供参考:

  1. feature_map 建议抽离到配置文件(JSON/YAML),不要硬编码在 Python 文件里。这样业务人员也能直接编辑,不用改代码。
  2. 去重策略要统一:按功能点名称去重是最简单的方案。如果业务更复杂,可以考虑按「名称 + 模块」组合去重。
  3. 预留扩展点 :在匹配逻辑里留一个 custom_rules 钩子,让特殊业务可以绕过关键词匹配,直接返回自定义功能点列表。
  4. 加单元测试:规则引擎看起来简单,但关键词交叉匹配时很容易出边界问题。建议至少覆盖:单关键词、多关键词、无匹配、兜底策略 4 种场景。
  5. 监控 feature_map 命中率:记录每次匹配命中了哪些关键词、走了多少次兜底策略。兜底比例过高(>30%)说明 feature_map 需要扩充了。

八、规则引擎的边界在哪里

规则引擎的优势是快、便宜、结构统一。但它的局限也很明显:

  • 只能覆盖预定义的关键词。遇到"元宇宙"、"Web3"这种新词,feature_map 里没有映射,只能走兜底策略。
  • 生成的用例不够具体。「执行正常操作流程」这种步骤描述,放之四海而皆准,但也意味着不够具体。真正执行的时候,测试工程师还是要手动细化。
  • 缺少业务深度。规则引擎不知道你的业务逻辑是什么,它只是按模板填空。真正的测试设计还需要测试工程师结合业务经验来补充。

所以我们的策略是:规则引擎出基础用例 → AI Skill 做精细打磨 → 测试工程师最终评审。三层过滤,效率和质量都有保障。


下篇预告:第3篇讲 LLM Skill 怎么调用大模型生成高质量用例------Prompt 设计、质量评分、容错处理,一个都不能少。

相关推荐
counterxing6 小时前
Agent 跑起来之后,难的是复用、观测和评测
node.js·agent·ai编程
uccs7 小时前
大模型底层机制与Agent开发
agent·ai编程·claude
counterxing7 小时前
我把 Codex 里的 Skills 做成了一个 MCP,还支持分享
前端·agent·ai编程
夜雪闻竹7 小时前
vectra 向量索引文件损坏怎么办
ai编程·向量·vectra
ZzT8 小时前
Harness 到底指什么
openai·ai编程·claude
宅小年8 小时前
AI 创业最危险的地方:太容易做出来
openai·ai编程·claude
麦客奥德彪8 小时前
Android Skills
架构·ai编程
言萧凡_CookieBoty9 小时前
一文讲清 RAG:让 AI 读懂业务知识库的核心方法
ai编程
冬奇Lab9 小时前
Agent 系列(一):Agent 是什么——不只是「会调工具的 LLM」
人工智能·llm·agent
冬奇Lab9 小时前
RAG 系列(二十四):代码 RAG——让 AI 理解你的代码库
人工智能·llm