多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

TestGPT:大模型应用自动化测试与质量回归实践

TestGPT:大模型应用自动化测试与质量回归实践 做了一段时间大模型应用之后我发现最让人头疼的不是写代码也不是调Prompt而是怎么证明这个模型在下个版本、下一次部署、甚至换一个模型底座之后它仍然会给出预期质量的结果。传统的自动化测试在大模型面前基本失灵因为输出不再是一个固定的字符串而是无限接近自然语言的长文本。后来我们在项目中引入TestGPT这套面向大语言模型的测试框架逐渐把模型测试从“靠人工点一点”变成了“可重复、可追踪、可回归”的工程化流程。这篇把TestGPT的使用思路、实际配置、用例编排和踩坑记录整理出来尽量做到让没有做过大模型测试的人也能照着落地。内容适合正在做AI应用、对模型输出质量有要求以及想在项目中建立自动化质量保障的开发和测试同学参考。1. 为什么大模型测试不能只用传统自动化手段1.1 传统测试与模型测试的根本差异先想一个最简单的场景你在测一个登录页面输入用户名密码点击登录断言“跳转成功”。这种测试的前提是输入输出完全确定期望结果可以用精确字符串和状态码来表示。可大模型不一样。同一个Prompt今天问明天问只要模型版本不动、参数不动输出可能还是会有差别再换一种问法表达方式完全不同但意思又是对的。传统断言根本接不住这种“语义正确但文本不同”的情况。另一个差异在于“测试预期怎么写”。传统测试里预期结果是枚举出来的比如返回200、返回空数组、返回特定错误码。但大模型的输出空间几乎是无限的你没法把“所有正确答案”都列出来。举个例子让模型写一段产品文案只要关键词覆盖、语气符合要求、不出现常识错误这条用例就算过。这个判断标准本质上是模糊的需要借助规则、相似度、甚至另一个模型来做评估。还有一个容易被忽略的点传统测试执行环境相对稳定测试用例一旦写好结果基本可复现。而模型测试的结果会受到温度、随机种子、上下文长度、系统Prompt甚至模型服务端负载影响。这些因素让“稳定执行”这件事本身就成了难题所以在方案选型时一定要把“不确定性管理”纳入设计而不是假装它不存在。1.2 TestGPT解决的是“判断标准”和“回归机制”的问题TestGPT的核心思路是把传统测试中“脚本驱动”变成“场景评估器驱动”。它有三个关键抽象用例、执行器、评估器。用例描述的是“我要测什么场景”执行器负责任务回放和请求记录评估器负责给模型输出打分。也就是说你不用在用例里写死“答案必须等于某某字符串”而是写“答案应该包含某关键词”“答案的语义相似度应该达到0.8以上”“答案不能包含敏感词”这种可计算的标准。这样带来的最大好处就是用例可复用当模型从A版本切换到B版本你不需要重写整套用例只需要跑一遍看哪些老用例开始失败失败的原因是什么。我见过一些团队把大模型测试做成“今天试几个Prompt感觉结果不错就上线”这在功能简单、用户量小的时候够用但一旦应用变复杂、模型版本频繁升级就会反复出现“我明明之前测是好的怎么现在不行了”的情况。TestGPT这类工具存在的意义就是把“感觉还行”变成“哪里行、哪里不行、跟哪个版本比”让问题可以定位、可以回归。1.3 常见误区TestGPT不是简单用GPT去测GPT我第一次听到这个概念时也以为是用一个大模型出题另一个大模型答题然后互相打分。实际用下来发现TestGPT本质是一个测试编排框架它可以调用关键词断言、相似度断言、代码执行断言也可以让一个固定的裁判模型来做LLM评判还可以把结果推给人做人工复核。所以不要被名字带偏TestGPT的边界不是“AI在测AI”而是“任何能产生可计算结论的评估方式都可以作为断言的插件”。这一点想清楚了后面配置用例和选型评估器时就会顺手很多。评估器可以是规则可以是模型可以是代码也可以是人工关键是判断标准要统一、要可重复。2. 用例设计与场景沉淀决定了TestGPT的上限2.1 先学会写出一个标准用例TestGPT的用例通常是一个结构化文件我习惯用YAML格式因为可读性好、容易进版本管理。一个最简单的用例大致包含id、标题、触发输入、预期表现和评估规则。id: tc_001 title: 商品推荐根据用户偏好推荐合适商品 tags: - recommend - functional setup: temperature: 0.2 messages: - role: system content: 你是一个购物助手回答需要简洁推荐商品后给出理由。 - role: user content: 我喜欢跑步预算500元左右推荐一双跑鞋。 expected: - 推荐结果中出现至少一个跑鞋品牌或跑鞋类目 - 推荐理由中包含“缓震”或“轻量”等专业性描述 - 不要出现与跑步无关的品类 asserters: - type: llm_judge prompt: | 请判断以下回答是否满足要求 1. 是否推荐了跑鞋类商品 2. 推荐理由是否包含运动专业性描述 3. 是否出现无关品类 只回答 PASS 或 FAIL不解释。 timeout: 30这里最需要注意的是messages里包含了完整的交互上下文。大模型是无状态接口大多数场景下你需要把系统角色、用户诉求、历史消息都放进来用例才有复现价值。2.2 断言器的选型别一把梭用模型打分TestGPT支持多种断言器我最常用的是四种关键词规则、语义相似度、代码执行和LLM评判。每一种都对应不同的场景。断言方式适用场景优点缺点关键词包含/排除格式校验、敏感词、结构约束速度快、结果稳定无法处理同义表达语义相似度开放问答、文本摘要容忍同义改写需要embedding模型阈值调起来烦代码执行代码生成、数据提取验证可运行性很硬核环境依赖较重LLM评判语气、风格、推理合理性接近人工判断成本高、可能误判选型原则其实很简单能用规则就用规则规则表达不了才上模型。比如你测试一个SQL生成功能最靠谱的断言是“把模型生成的SQL扔到测试库里执行一遍不报错而且结果集符合预期”这比任何模型打分的说服力都强。而如果你的功能是“写一段感谢客户的邮件”关键词规则就不好使此时语义相似度或者LLM评判反而是合理选择。2.3 场景库的建设从真实会话中挖场景而不是凭空编我踩过最大的坑就是团队拍脑袋写用例。几个人坐在一起想“模型可能会被问这些问题”然后写出一堆自己以为很合理的Prompt结果模型在真实用户面前的表现完全不是那回事。真正高效的做法是从线上日志里捞真实会话。方法和步骤我梳理过几次收集一段时间内用户输入按功能模块分类。聚类高频问题形成Top场景。对每个场景人工标注“哪些是正确的模型回答”沉淀成参考回答。把参考回答变成用例中的expected或者golden answer。这样做的好处是场景库是跟着用户需求走的不是跟着猜测走的。而且验证通过率的时候你可以说“高频用户问题中92%场景表现合格”这种数据在质量管理上非常有说服力。我建议目录结构按照业务模块划分不要全堆在一个文件里。比如cases/ recommend/ tc_001_basic.yaml tc_002_edge.yaml customer_service/ tc_101_refund.yaml content_safety/ tc_201_sensitive.yaml标签体系也很重要每条用例打上functional、safety、boundary、performance这类标签后面做回归筛选时就灵活了。3. 从零搭建一套TestGPT实例3.1 环境准备与安装TestGPT本身是Python技术栈建议在Python 3.10及以上版本环境里使用。我习惯先在项目目录下创建独立的虚拟环境避免污染其他项目依赖。python -m venv .venv source .venv/bin/activate pip install testgpt装完之后可以用命令检查版本确认安装成功。testgpt --version如果网络环境受限也可以从本地仓库构建这里就不展开说了。整体安装过程比较顺没有复杂的系统依赖。3.2 配置模型接入与全局参数TestGPT本身不绑定具体模型厂商它通过标准HTTP接口与模型服务交互。我们需要在配置文件里指定目标模型的服务地址和访问凭据。出于安全习惯密钥不要直接写在配置文件里建议用环境变量注入。model: endpoint: ${MODEL_API_ENDPOINT} api_key: ${MODEL_API_KEY} model_name: gpt-oss-7b temperature: 0.2 max_tokens: 1024 execution: concurrency: 4 timeout: 60 retries: 2 report: output_dir: ./reports这里有个容易忽略的细节temperature一定要在配置里体现。有些模型的默认温度可能很高导致同样的用例每次执行结果都不一样后面调断言时会非常痛苦。建议采用双温度策略测试阶段用较低温度来稳定结果另外单独留一组用例在高温度下跑用来评估模型在创造性场景下的表现上限。3.3 编写第一个可执行的测试用例把前面那个商品推荐的用例保存为cases/recommend/tc_001_basic.yaml然后就可以执行了。先跑单个用例确认配置没问题testgpt run cases/recommend/tc_001_basic.yaml执行过程中TestGPT会把请求内容、模型原始返回、每个断言的结果都记录下来。我第一次跑的时候完全没看输出直接看结论结果发现用例标红原因是“推荐理由中缺少专业性描述”。后来打开详细日志发现模型确实推荐了跑鞋但理由写得太口语化没有出现“缓震”“轻量”这些词。这里要特别提醒关键词断言过细很容易误伤正常的自然语言表达。遇到这种情况我的处理方法是把断言改成同义词组比如“缓震或减震或回弹”而不是写死一个词。这也是TestGPT的用例设计思路规则要贴近业务语义而不是追求字面强制。3.4 批量执行、报告解读与调试多个用例批量执行也很直接testgpt run cases/ --report html执行结束后会在./reports目录下生成报告。报告里我重点看三项内容通过率、失败用例排名、失败分类。通过率就不用多说了失败用例排名直接告诉你是哪一类场景集中出问题比如客服类失败多可能是模型对退款政策理解有问题。失败分类则帮助判断是断言规则太严格还是模型真的产生了错误回答。想快速定位单个用例问题时推荐用调试模式testgpt debug cases/recommend/tc_001_basic.yaml调试模式会展示完整的请求和响应还能看到每一步断言的中间结果。我在调LLM评判器的Prompt时几乎都会用这个命令因为直接看结果比打开报告要快得多。4. 接入流水线、回归策略与成本控制4.1 把TestGPT接入持续集成测试工具如果只躺在本地跑价值就少了一半。我们在项目中做了流水线集成方式很简单在代码提交触发后并行跑一轮冒烟测试testgpt run cases/ --tag smoke --fail-fast --report junit这里--tag smoke只执行打了smoke标签的用例--fail-fast表示一旦有关键用例失败就中止执行适合快速反馈。输出的JUnit格式报告可以直接被大多数CI系统解析在提交记录上直接显示通过或失败。接入CI之后回归就成了自动动作。模型服务端一旦更新权重不用谁发起流水线自动帮你验证一下线上功能有没有系统性退化。我见过太多“模型升完级线上用户才发现变傻了”的情况这个环节其实能拦下一大批问题。4.2 三级测试策略冒烟、回归、全量不同的执行场景对用例数量和耗时的要求完全不同。如果每次提交都跑全量用例反馈速度会拖垮团队如果只跑冒烟又容易出现漏网之鱼。我们最终采用了三级策略效果比较理想级别覆盖范围执行频率耗时准入门槛冒烟核心链路Top 30条用例每次提交2-5分钟必须全过回归全部功能和部分安全用例每日或版本验证15-30分钟允许少量波动需人工复核全量全量用例含长尾、压力场景每周或发版前1-2小时无P0问题通过率不低于基线冒烟场景选的是用户最高频的路径比如“商品推荐结果不为空”“客服回答包含退换货政策关键信息”。全量场景除了功能还会覆盖边界条件和合规内容这部分用例跑起来慢而且容易消耗大量Token所以不放在高频CI里。4.3 成本控制与执行速率调优大模型测试和传统测试最大的区别是跑用例是有真金白银的Token成本的。一些团队舍不得跑测试覆盖率上不去另一些团队跑得太猛月底预算爆炸。我的建议是把成本维度纳入用例设计。具体做法是在每个用例文件里标注预估Token消耗cost: max_tokens: 800 estimated_cost: 0.002TestGPT会按当前配置的计费标准换算成本报告里汇总一轮执行的总开销。这样在决定“要不要每天跑全量”时就有依据了。并发数设置也有讲究。太高的并发会导致模型服务延迟明显上升超时失败增多反而拖慢整体速度太低的并发又浪费资源。我一般从4开始观察模型服务的P95延迟逐步往上调。另外如果用例之间存在重复的上下文或者长系统Prompt可以开启缓存功能命中后直接复用结果能省下不少Token。5. 常见问题与真实踩坑记录5.1 用例结果波动大怎么定位稳定性问题这是大模型测试最常遇到的坑。同一个用例上午跑通过下午跑失败看输出内容又感觉差不多很容易让人抓狂。我的排查顺序是先看温度和随机种子。若测试环境温度较高输出本身不够稳定建议降到0附近。再看断言类型如果用例用的是“必须包含某个关键词”模型只要换一种说法就会挂掉这属于断言过严。如果上述都没问题那就要怀疑模型版本是否发生了变化。有些模型服务端会做灰度切换同一个接口背后可能混用了不同版本的权重。此时让TestGPT在执行时记录模型返回的版本字段再对比报告里的版本分布通常一眼就能看出来。最后一种情况是上下文注入导致的结果漂移。比如某些用例中历史消息过长模型“忘掉”了部分指令输出就飘了。这种情况建议减少固定上下文长度把核心约束放到每条用户消息里重复一遍。5.2 LLM评判器误判怎么处理用LLM评判器做断言时最大的风险是裁判模型有自己的偏好。比如有些裁判模型会倾向给长答案高分或者只要回答里出现了几个关键词就默认通过哪怕逻辑根本不对。我们曾经出现过一类场景模型回答得前言不搭后语裁判还是给了PASS因为“语气有礼貌”。我的经验是裁判Prompt里要刻意加入否定条件请判断以下回答是否满足要求。 注意如果回答中存在事实性错误或者逻辑前后矛盾即使语气良好、长度充足也必须判FAIL。另一个有效手段是把裁判模型和被测模型分开。如果两者是同一个模型自评偏差会被放大。在预算允许的情况下用一个更全面、版本更新的模型作为裁判效果会好很多。但这也意味着成本上升所以我会搭配人工抽检策略按1:10的比例抽样人工复核裁判结果持续标定裁判质量。5.3 长耗时用例和不稳定连接怎么解决大模型接口经常会出现偶发性超时。TestGPT里有超时和重试参数但设置的时候要注意区分两类超时单次请求超时和整体用例超时。单次请求超时通常设在30-60秒整体用例超时建议至少是请求超时的两倍因为大模型推理在复杂场景下真的很慢。如果模型端支持流式输出建议开启流式响应首Token延迟通常会明显低于整体完成延迟可以有效减少超时误报。另外如果确实碰到服务端不稳定的情况可以开启执行断点续跑让已完成的用例不重复执行只重跑失败的段落。这个功能在跑全量用例时特别有用能节约大量时间和成本。5.4 切换模型底座之后原有用例如何迁移团队会面临换模型的情况比如从某个开源模型切到另一个更大参数的模型或者在不同场景下使用不同的模型。刚开始直接跑原有用例库时大概率会看到一批失败。这里面有些是模型能力差异导致的真失败有些则是老模型输出风格固化新模型只是换了种说法语义上是正确的。区分这两类问题的思路是同一个失败用例把断言方式从“关键词包含”临时切换成“语义相似度”如果相似度得分很高说明模型理解没问题只是表达方式变了那就可以把用例的断言改得更宽松一些。如果相似度得分也很低那基本可以确认是功能性问题需要拉人去分析模型权重或者Prompt设置。换模型之后还应该重新生成一次基准分数线。新旧模型的“平均通过率”不能直接对比因为用例库的阈值是按老模型的输出习惯调的。建议以新模型跑完第一轮全量用例的结果为基线后续版本的回归都以这个基线为参照。我在实际使用过程中最大的体会是TestGPT本身不复杂真正决定质量的是场景库的质量和维护频率。工具只能把你的判断标准自动化但标准本身需要业务人员、开发、测试一起持续打磨。建议从一小撮核心场景开始用起不要一上来就铺全量先跑通一条收益最大的链路等团队习惯了“用数据说话”的工作方式再逐步扩大覆盖面。这样无论是接受度还是稳定性都会顺畅很多。
返回列表