上个月给一个订单模块加幂等校验,逻辑本身不复杂——同一个业务单号在 30 秒内的重复请求只处理第一次。但写到测试用例的时候卡住了:正常路径的用例几分钟就列完了,边界条件却总觉得漏了什么。补偿失败的场景要不要测?并发同时到达但时间戳差几毫秒的情况怎么设计用例?Redis 锁超时后的回滚路径该不该覆盖?

手头的测试用例评审还差两天,我决定先让 AI 帮忙把边界条件补一轮,自己再做筛选和验证。试了三个模型,输出差异比我预想的大得多。

为什么同一个任务不同模型给出的答案差这么多

我把同一份接口文档和已有的正常路径用例喂给三个模型,要求输出“补充的边界条件测试用例,格式为表格”。结果是三份风格完全不同的产出。

DeepSeek 的用例最贴近实际工程场景。它补了 11 条边界用例,其中有一条是“Redis 锁写入成功后业务处理超时,锁自动过期,第二个请求进入——此时幂等键对应的业务状态为处理中”。这个场景我原来确实没想到,但线上出过类似的问题。它的中文表达也自然,没有明显的直译感。

ChatGPT 给的用例结构更工整,表格里每列的颗粒度很细,前置条件、输入参数、预期结果分得很清楚。但它编了一条“验证幂等键过期后再次请求时数据库自增 ID 回退”的用例——这个模块根本没有用数据库自增 ID,显然是模型在“合理推断”时假设了实现细节。这就是典型的 API 幻觉:它不知道你具体怎么实现的,就会用训练数据里的常见模式来补。

Claude 的覆盖面最广,给了 18 条用例,包括并发场景、网络超时、数据库死锁回滚等。但有几条用例的前提条件和我们的技术栈不一致,比如它假设了分布式锁用的是 ZooKeeper,而我们实际用的是 Redis 单实例。这 18 条里真正能直接用的大概 12 条,剩下的要么改前置条件,要么标记为不适用。

三者放在一起看,DeepSeek 更适合中文环境下的工程实践补充,ChatGPT 擅长结构化输出但要防幻觉,Claude 覆盖广但需要人工过滤技术栈不匹配的部分。没有一个模型能“拿来就用”,但三者交叉验证后,遗漏的边界条件确实少了很多。

Prompt 怎么写才能让模型输出可用的测试用例

第一轮我用的 Prompt 很随意:“帮我补充这个接口的测试用例,重点是边界条件”。三个模型的输出都偏通用,没什么针对性。

第二轮调整后,我用的 Prompt 如下:

角色:你是一个有 5 年经验的测试开发工程师,熟悉 Java 后端系统和幂等设计方案。
背景:一个订单服务的幂等校验接口,基于 Redis 实现幂等锁,锁过期时间 30 秒。
输入材料:
- 接口路径:POST /api/order/submit
- 请求参数:orderId(业务单号)、userId、amount、timestamp
- 幂等逻辑:同一 orderId 在 30 秒内只处理第一次请求,后续返回“处理中”
- 异常处理:Redis 不可用时降级为数据库唯一索引兜底
任务:补充边界条件测试用例,重点关注以下场景:
- 并发场景(时间差小于 10ms 的重复请求)
- Redis 锁超时场景
- 降级路径(Redis 不可用时的行为)
- 补偿逻辑(业务处理失败后的幂等状态回滚)
输出格式:Markdown 表格,列包括“用例编号|场景分类|前置条件|输入参数|预期结果|优先级”
限制条件:
- 不要假设数据库使用自增 ID
- 不要引入文档中未提到的中间件
- 如果某个场景缺少信息无法设计用例,标注“信息不足,无法设计”
验证要求:每条用例的预期结果必须可以直接用接口返回码或数据库状态来验证,不能写“系统行为正常”这类模糊描述。

这个 Prompt 里真正起作用的约束有四个:

一是技术栈限制,明确说了“不要假设数据库使用自增 ID”,直接堵住了 ChatGPT 上次编造的那类错误。二是降级路径指定,说明 Redis 不可用时的兜底方案,让模型在有边界条件约束的情况下做推断,而不是凭空猜。三是输出可验证性要求,强制预期结果必须是可观测的返回码或数据库状态,杜绝“行为正常”这种没法测试的描述。四是信息不足时的处理方式,要求模型诚实标注“信息不足”,而不是硬编。

模型的输出怎么验证

测试用例这类产出有个特点:看起来都对,不代表能直接用。我的验证流程是这样:

第一步:技术栈一致性检查。 逐条看用例的前置条件,把提到文档中没有的中间件、API、数据库特性的条目挑出来。ChatGPT 那批里有 3 条因为这个问题直接打了回去。

第二步:可执行性核对。 预期结果是否可以直接用接口返回码验证?是否涉及需要 mock 的外部依赖?如果有需要 mock 的场景,确认 mock 的成本是否值得。Claude 有一条用例需要模拟 Redis 在写入后的第 29 秒刚好挂掉,这个在本地环境基本没法精准构造,标记为“暂不纳入本次测试范围”。

第三步:用另一个模型做反向检查。 把筛选后的用例和原始接口文档一起发给 DeepSeek,要求它“找出这些测试用例中可能遗漏的场景”。它补了 2 条,其中一条是关于降级路径的恢复场景——Redis 恢复后,新的请求应该重新走幂等锁逻辑,而不是继续走数据库唯一索引。这条确实之前漏了。

第四步:人工终审。 最后把用例表交给模块负责人过一遍,确认业务逻辑没有理解偏差。这一步花的时间最少,因为前面的筛选已经把大部分明显问题剔掉了。

四个步骤走下来,从 18 + 11 + 15 条原始产出中,最终保留了 16 条可用的边界用例,另外有 4 条修改前置条件后可用,5 条直接排除。这个筛选比例大概 50%,比直接手写节省了时间,但绝不是“交钥匙”级别的自动化。

多模型交叉验证的意义在哪

做完这轮之后我的判断是:单一模型出测试用例的风险在于,你不知道它漏了什么。而用两个以上模型做同一任务,差异点往往就是值得人工细看的地方。

三个模型的差异集中在这几类:

  • 对实现细节的假设不同(ChatGPT 假设了自增 ID,Claude 假设了 ZK)

  • 对场景优先级的判断不同(DeepSeek 倾向高频真实场景,Claude 倾向理论上的全覆盖)

  • 对降级路径的关注程度不同(DeepSeek 和 Claude 都提了降级,ChatGPT 只提了一条)

  • 中文表达的可用性不同(DeepSeek 和 ChatGPT 可以,Claude 偶有直译腔)

差异最大的那几个点,恰恰是最需要人工介入的地方。如果只用了一个模型,这些差异你根本看不到。

代码示例:用例格式校验脚本

模型输出的表格格式不一定规范,有时多一列少一列,或者分隔符没对齐。我写了个简单的 Python 脚本做基础校验,避免人工检查格式的低效:

import re

def validate_testcase_table(md_table):
    """检查测试用例 Markdown 表格的列数和必填字段"""
    lines = [l.strip() for l in md_table.split('\n') if '|' in l]
    if len(lines) < 2:
        return False, "表格为空或行数不足"
    
    # 去掉分隔行
    data_lines = [l for l in lines if not re.match(r'^\|[\s\-:]+\|$', l)]
    if not data_lines:
        return False, "无数据行"
    
    # 校验列数一致性
    col_counts = [len(l.split('|')) - 2 for l in data_lines]
    if len(set(col_counts)) > 1:
        return False, f"列数不一致: {set(col_counts)}"
    
    # 校验必填列(预期结果列不能为空)
    for i, line in enumerate(data_lines[1:], start=2):  # 跳过表头
        cells = [c.strip() for c in line.split('|')[1:-1]]
        # 假设预期结果在倒数第二列
        if len(cells) >= 2 and not cells[-2]:
            return False, f"第{i}行预期结果列为空"
    
    return True, "格式校验通过"

# 示例:模型输出的表格粘贴到这里
test_table = """
| 用例编号 | 场景分类 | 前置条件 | 输入参数 | 预期结果 | 优先级 |
|----------|----------|----------|----------|----------|--------|
| TC-001 | 正常幂等 | Redis正常 | orderId=A001 | 返回200 | P1 |
"""

ok, msg = validate_testcase_table(test_table)
print(f"校验结果: {msg}")

这类脚本逻辑简单、边界清晰,交给 AI 生成后跑一遍就能确认,属于低风险可信任任务。但即便如此,生成后我也会在本地跑一次,确认能正常执行。

风险边界:哪些信息不能给模型

测试用例设计涉及接口定义、业务逻辑和异常处理路径,这些信息传给模型前必须做脱敏:

  • 接口路径和参数名保留,但真实域名、内网 IP、Token 全部替换

  • 业务单号的生成规则不要暴露,用模拟格式代替

  • 不要贴完整的配置文件和数据库连接信息

  • 公司内部的系统架构、部署拓扑、容量数据不能给

  • 模型的输出中如果出现了“看起来合理但你没提到过的实现细节”,那就是编造的,必须删掉或验证后再用

还有一个容易忽略的点:如果你用模型交叉验证,不要把 A 模型的输出原封不动地喂给 B 模型并要求“找出 A 的问题”。这样 B 模型会受 A 的影响,相当于两个裁判共享了信息。正确的做法是先让两个模型独立输出,再做人工对比。

常见误区

Q:AI 生成的测试用例能直接写入测试计划吗?

不能。需要经过技术栈一致性检查、可执行性核对和人工终审。模型可能编造不存在的 API、假设你用某个特定中间件、或者漏掉业务特有的边界场景。

Q:一个模型出用例够用吗?

不够稳。单一模型你不知道它漏了什么。用两个模型独立生成,差异点往往就是需要人工重点看的地方。

Q:怎么避免模型编造 API 和中间件?

在 Prompt 里明确列出你实际使用的技术栈,并加入限制条件:“不要引入未在输入材料中提到的中间件或 API”。如果仍然出现编造,说明模型在这个领域容易过度推断,换一个模型试试。

Q:技术文档和接口说明能直接发给 AI 吗?

需要脱敏后再给。IP、域名、Token、密钥、业务数据格式中的敏感信息都要替换,内部架构细节也建议抽象化处理。

Q:多模型交叉验证是不是哪个模型的结果最全就用哪个?

不是。模型输出一致不代表正确,输出冲突也不代表有一个错了。交叉验证的价值是帮你定位需要人工判断的差异点,最终决策权在人手里。

总结

这次用 AI 辅助测试用例设计的经验可以总结成一条:把模型当成“边界条件的补充者”,而不是“测试方案的起草人”。

从最小切口入手——选一个接口,整理好正常路径用例和技术栈说明,用约束清晰的 Prompt 让模型专注补充边界条件。输出后走一套固定的验证流程:技术栈一致性检查、可执行性核对、多模型交叉验证、人工终审。选模型时别想着找一个“全能的”,DeepSeek 做中文工程场景的边界补充最实用,ChatGPT 做结构化输出但要警惕幻觉,Claude 覆盖面广但需要过滤技术栈不匹配的部分。三个模型独立生成后做交叉对比,差异最大的地方就是最值得人工细看的地方。

所有涉及公司代码、接口、架构的信息都要脱敏,模型输出只是候选,不是结论。人工判断和安全边界不是限制 AI 的使用,而是让 AI 真正融入研发流程的前提。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐