基于DeepSeek API的智能测试用例生成实战指南

发布时间:2026/10/21 8:42:29

基于DeepSeek API的智能测试用例生成实战指南 简介面向自动化测试工程师与AI应用开发者的PDF技术文档系统讲解如何借助DeepSeek API构建智能用例生成方案。文档从自动化测试框架的基础类型与优势切入详细说明DeepSeek API的语言理解、文本生成、可定制性及处理速度等技术特点并围绕需求理解、用例生成、用例评估优化三个阶段阐述核心原理。实现部分覆盖环境搭建、需求文档处理、测试用例模板定义、调用API生成用例、覆盖率计算等关键环节附带完整Python代码示例与详细解释同时给出性能评估指标、优化策略以及电商平台、在线教育平台等应用场景分析帮助读者将方案直接用于实际项目。资源为单个PDF文件共23页压缩包大小约1.83MB图文目录清晰、无缺页乱码目前已有187人学习浏览。对希望借助DeepSeek提升测试效率、探索AI辅助用例生成的开发者而言这份资料兼具原理讲解与实操参考价值。1. 智能用例生成到底解决了什么自动化测试用例生成一直是人力密集的活。一个中型业务系统需求文档三五十页光梳理正常流程、异常分支、边界值就能耗掉测试同学两三天。基于 DeepSeek API 做智能用例生成方向是把需求文本变成结构化用例集让模型先理解业务规则再按边界、异常、权限、数据组合这些维度批量产出测试用例最后交给自动化测试框架直接执行。这套方案的适用人群很明确手里有接口测试或 UI 自动化框架、但用例维护成本高的团队以及想给测试提效的开发者。这里不聊玄学只讲怎么把这条链路从零搭起来、参数怎么设、会在哪里翻车。2. 选 DeepSeek API 做用例生成接口形态与 Prompt 工程调用 DeepSeek API 之前要认清一件事它是个文本补全服务不是聊两句就会自动帮你把测试计划写好的。你传一段 prompt它返回一段文本。所以智能用例生成的核心工作不在 API 文档上而在 Prompt 怎么写。常见做法是走 chat completions 接口messages 数组里放系统角色和用户内容系统提示词里设定角色约束用户消息里放需求文本和输出格式要求。选它而不是本地小模型图的是按 token 计费、中文理解到位而且不用自己准备显卡代价是需求文本要出网敏感项目别走这条路。2.1 关键参数温度、Top-P、Max Tokens 怎么影响用例生成用例生成和聊天不一样参数得按“稳定优先”来调。先说结论我一般用下面这套起步值参数起步值对用例生成的影响temperature0.2低温度减少随机性但太低会导致同一套路反复输出多样性下降top_p0.9配合 temperature 控制候选词范围一般不要和 temperature 同时拉到很高max_tokens4000决定单次返回上限太短用例被截断太长增加等待时间streamfalse用例生成整体解析不关流式容易拿到半截内容下面是带着超时控制的基础调用函数这是整个生成管线的地基import requests import os def call_deepseek(prompt, temperature0.2, max_tokens4000, top_p0.9): api_key os.environ.get(DEEPSEEK_API_KEY) if not api_key: raise RuntimeError(缺少 DEEPSEEK_API_KEY 环境变量) resp requests.post( https://api.deepseek.com/v1/chat/completions, headers{Authorization: fBearer {api_key}}, json{ model: deepseek-chat, messages: [ {role: system, content: 你是资深测试设计专家输出严格遵循用户要求的格式。}, {role: user, content: prompt}, ], temperature: temperature, top_p: top_p, max_tokens: max_tokens, stream: False, }, timeout120, ) resp.raise_for_status() data resp.json() return data[choices][0][message][content]逻辑说明这个函数把 API key、模型名、角色设定都集中在一处后面所有生成任务都复用它。messages里 system 消息写角色约束user 消息写实际任务这是 chat completions 接口的标准用法。timeout120很重要长 prompt 加 4000 token 的输出可能跑四五十秒默认超时太短会误判失败。参数怎么改要分场景说。temperature 在 0.2 到 0.4 之间是我试过比较稳的区间。拉到 0.8 以上模型会开始发挥把“登录密码错误提示”编成“短信验证码错误提示”用例长得漂亮但内容不可信。top_p 保持 0.9 就行如果需求文本里专有名词多、模型容易联想降到 0.85 能少一点幻觉。max_tokens 别抠门一条完整用例平均 200 token十条带前置条件和步骤说明就要 2000 以上我一般给到 4000配合后面要讲的分批生成不会截断。2.2 从需求文本到用例集两段式 Prompt 模板设计直接把整份需求文档塞给模型要求“生成 100 条测试用例”效果很差。原因有两个需求很长时业务规则被埋在一堆背景描述里模型抓不住重点其次一次性生成太多条容易出现前面的数据定义到后面就变了。我一般用两段式 Prompt把“理解需求”和“生成用例”分开这也是项目里最值得抄的设计REQ_EXTRACT_PROMPT 你是测试需求分析器。阅读下面的原始需求提取并输出 JSON不要输出其他内容 { business_flows: [{name: , steps: []}], business_rules: [{condition: , expected: }], error_scenes: [{trigger: , expected: }], permissions: [{role: , allowed_ops: []}] } 原始需求 {requirement_text} CASE_GEN_PROMPT 你是自动化测试用例设计器。基于结构化需求为每个业务规则生成测试用例。 输出必须是 JSON 数组每个用例对象格式 { id: TC_001, title: , precondition: , steps: [], test_data: {}, expected: , priority: P0|P1|P2, type: positive|negative|boundary|permission|combo } 要求每个业务规则至少 2 条正例、1 条反例边界值必须单独成条 只能使用结构化需求里出现的操作和字段不得新增任何元素名。 结构化需求 {structured_json} 逻辑说明第一段让模型把自然语言需求压成结构化 JSON相当于先做一轮信息抽取第二段再基于这个 JSON 派生用例。这么拆有两个实际好处。一是需求文本两万字时第一段先压缩成几千 token 的关键规则第二段不需要再背完整上下文token 成本直接降一截。二是中间的结构化 JSON 可以被开发同学 review业务规则错了直接改 JSON 再重跑第二段不用把第一段也重新生成一遍。这里几个参数和写法值得注意。第一段 temperature 可以给到 0.4信息抽取需要一点归纳能力第二段必须压到 0.2用例设计阶段要的是稳定而不是发散。两段式还会遇到一个新问题第二段生成的结果可能不是合法 JSON。先别急着骂模型这是必然现象后面第 5 章专门讲怎么兜底。常见误区是有人把 few-shot 示例塞在系统消息里而不是用户消息尾部导致模型模仿了示例的格式却忽略了任务要求我一般把示例直接写进 CASE_GEN_PROMPT 的结构说明里让模型照着 JSON schema 填比单纯说“请生成 JSON”稳得多。两段式串起来的调度逻辑很简单核心就是先调一次提取再调一次生成import json def generate_case_set(requirement_text: str): structured call_deepseek( REQ_EXTRACT_PROMPT.format(requirement_textrequirement_text), temperature0.4, ) cases_text call_deepseek( CASE_GEN_PROMPT.format(structured_jsonstructured), temperature0.2, ) # 这里先直接解析真实项目要套容错解析见第 5 章 return json.loads(cases_text)这个函数看起来短但它是整个智能生成方案的心脏。后面要加覆盖增强、去重、反馈迭代都是在这个调用链路上挂新逻辑。3. 搭一个最小可运行的用例生成管线从需求文档到 JSON 用例有了 Prompt 模板接下来要做的是把它变成一条能反复使用的生成管线吃进一份需求文档吐出一批可执行的结构化用例。第 2 章讲的是单次生成这一章讲的是工程化。目标是让项目里任何一个测试同学都能跑而不是只有写脚本的人能玩。3.1 项目结构与核心脚本我习惯的最小目录长这样四个文件不引入任何测试框架依赖case_generator/ ├── config.py # API key、模型名、参数默认值 ├── deepseek_client.py # 封装 call_deepseek 和重试 ├── generator.py # 两段式生成主逻辑 └── run_pipeline.py # 命令行入口串起整个流程这个结构的选型理由很简单配置、客户端、业务逻辑、入口四层分离。config.py 里放环境变量读取deepseek_client.py 放网络调用和重试generator.py 放 Prompt 模板和组装逻辑run_pipeline.py 只负责命令行参数解析和流程编排。等后面要接 pytest 或者企业微信通知只改入口层不动生成逻辑。run_pipeline.py 的核心入口用 argparse 接收参数这是最小可用的命令行设计import argparse import json import os from generator import generate_case_set def load_requirement(path: str) - str: with open(path, r, encodingutf-8) as f: return f.read() def save_jsonl(cases: list, output_path: str): with open(output_path, w, encodingutf-8) as f: for case in cases: f.write(json.dumps(case, ensure_asciiFalse) \n) def main(): parser argparse.ArgumentParser(descriptionDeepSeek 智能用例生成管线) parser.add_argument(--input, requiredTrue, help需求文档路径支持 txt/md) parser.add_argument(--output, defaultcases.jsonl, help输出文件路径) parser.add_argument(--batch-size, typeint, default10, help每批生成用例数量上限) args parser.parse_args() requirement load_requirement(args.input) cases generate_case_set(requirement) save_jsonl(cases, args.output) print(f生成完成{len(cases)} 条用例 - {args.output}) if __name__ __main__: main()运行方式就一行export DEEPSEEK_API_KEY你的key python run_pipeline.py --input docs/订单需求.md --output cases/订单需求.jsonl逻辑说明入口脚本不直接调模型而是调用 generator 里的 generate_case_set后面换参数、加去重都不影响命令行。jsonl 输出是我刻意选的不用一个大 JSON 文件因为每条用例独立一行测试框架逐行读取时哪一行出错就定位哪一行多人同时改文件也不容易冲突。print 那行是给命令行交互看的真实项目可以替换成日志。3.2 生成、格式校验、入库的完整流程光把用例生成出来还不够大模型输出不可控必须加一道格式校验闸门不合格的用例不能进文件。常见做法是生成后先做 schema 校验再写入 jsonl。校验函数长这样REQUIRED_FIELDS {id, title, precondition, steps, expected, priority, type} VALID_PRIORITY {P0, P1, P2} VALID_TYPE {positive, negative, boundary, permission, combo} def validate_case(case: dict) - list: errors [] missing REQUIRED_FIELDS - case.keys() if missing: errors.append(f缺少字段: {missing}) if not isinstance(case.get(steps), list) or not case.get(steps): errors.append(steps 必须是非空数组) if case.get(priority) not in VALID_PRIORITY: errors.append(fpriority 非法: {case.get(priority)}) if case.get(type) not in VALID_TYPE: errors.append(ftype 非法: {case.get(type)}) return errors def validate_batch(cases: list) - tuple: valid, invalid [], [] for i, case in enumerate(cases): errs validate_case(case) if errs: case[_error] errs invalid.append(case) else: valid.append(case) return valid, invalid参数说明REQUIRED_FIELDS 集合定义了用例的字段契约这是为了和自动化测试框架对齐。priority 和 type 用枚举校验防止模型输出“高中低”这种我们框架不认的写法。validate_batch 返回两个列表而不是直接抛异常是为了让流程继续处理合法用例同时把不合法的单独落盘供人工 review。这一步看起来多余但它能拦截掉大模型至少三成的“长得像用例但没法执行”的输出。完整流程还缺一个需求文档往往很长一次生成 50 条用例容易截断。所以 generate_case_set 内部要按 batch_size 拆每批只让模型生成 10 条左右。拆批不是简单切片而是让模型每批聚焦一个业务规则避免上下文被冲散。调整第 2 章的 generate_case_set让它接受 batch_size并且对结构化 JSON 里的 business_rules 循环生成def generate_case_set(requirement_text: str, batch_size: int 10): structured_text call_deepseek( REQ_EXTRACT_PROMPT.format(requirement_textrequire文本前2000字) ) structured json.loads(structured_text) rules structured[business_rules] all_cases [] for i in range(0, len(rules), batch_size): batch rules[i:i batch_size] batch_json json.dumps({batch_index: i // batch_size, rules: batch}, ensure_asciiFalse) cases_text call_deepseek( CASE_GEN_PROMPT.format(structured_jsonbatch_json) ) cases parse_cases(cases_text) all_cases.extend(cases) return all_cases逻辑说明外层循环按业务规则分批每批的 prompt 里只放当前这批规则。这样做的好处是每批的上下文小、模型聚焦坏处是调用次数变多、耗时增加。batch_size 的设置我一般压在 5 到 10 条规则之间超过 15 条输出质量和稳定性都会下降。如果你遇到“第一批很好第二批开始重复”的现象优先把 batch_size 调小而不是去调 temperature。第 2 章生成的是单批用例这一章把它变成循环调度、批量校验、落盘的标准管线。到这里你已经可以用一份需求文档跑出一份 jsonl 用例文件了。但实测跑下来你会发现用例是有了覆盖经常偏科正例一抓一大把反例和边界值少得可怜。这是下一章要解决的问题。4. 覆盖增强与去重策略不只要生成还要生成得稳用例数量多不等于质量好。直接用两段式流程跑出来的用例集最常见的问题是覆盖集中模型默认先写正常流程反例写几条意思一下边界值基本靠运气。这章讲两个手段一个是在生成侧做覆盖增强按维度拆解而不是一次大而全另一个是在校验侧做去重和合并把模型爱说车轱辘话的毛病治掉。4.1 覆盖增强按维度拆解需求不靠一次大 Prompt我用的方法很朴素把用例按维度拆成五类每个维度单独生成单独评估覆盖情况。五个维度是 positive 正常流程、negative 异常流程、boundary 边界值、permission 权限、combo 多条件组合。每个维度给不同的数量和指令temperature 也可以不一样。DIMENSIONS { positive: { count: 5, instruction: 覆盖主流程和关键分支流程每个流程至少一条用例步骤必须完整。, temperature: 0.2, }, negative: { count: 5, instruction: 覆盖非法输入、异常操作、依赖服务不可用、中间步骤失败等场景。, temperature: 0.2, }, boundary: { count: 3, instruction: 覆盖边界上下限、长度限制、分页边界、数值精度边界。, temperature: 0.2, }, permission: { count: 3, instruction: 覆盖无权限、部分权限、越权访问、角色切换后的权限变化。, temperature: 0.3, }, combo: { count: 2, instruction: 覆盖多个边界条件同时出现、多个异常场景叠加的组合用例。, temperature: 0.3, }, } def generate_by_dimensions(structured_json: str) - list: all_cases [] for dim, conf in DIMENSIONS.items(): prompt f 你是自动化测试用例设计器。 针对维度“{dim}”生成测试用例数量 {conf[count]} 条。 {conf[instruction]} 输出 JSON 数组字段格式不变。 结构化需求 {structured_json} cases_text call_deepseek(prompt, temperatureconf[temperature]) all_cases.extend(parse_cases(cases_text)) return all_cases逻辑说明把一次大生成拆成五次小生成单次返回更稳定每个维度还能单独肉眼检查。temperature 设置上positive 和 boundary 用低温度保证步骤准确permission 和 combo 用 0.3 稍微放一点发散因为权限组合和条件组合需要模型多做一点“排列组合”。count 的配比可以根据业务调整我上面的 5/5/3/3/2 是针对订单类接口的考古调法如果你的系统登录相关功能多permission 的占比可以提到 5。这里有个关键点维度拆分之后结构化需求 JSON 不需要重新抽取一次抽取结果能喂给五个维度省了重复 token。这也正是第 2 章两段式设计的收益。实际跑的时候你会看到 negative 维度经常生成一些“网络断开”“数据库超时”这类依赖注入的场景这些用例在接口测试里能直接模拟在 UI 自动化里执行起来成本很高。所以我会在 negative 的 instruction 里加一句“优先选择可模拟的异常如接口返回错误码、字段非法”把玄学场景挡在外面。4.2 去重与合并相似度判重和路径冲突处理维度拆完下一步是去重。你跑几轮之后会发现模型特别喜欢用不同措辞描述同一个操作“点击登录按钮”和“按下登录键”意思完全一样。去重不能只靠完全匹配字符串得算相似度。轻量方案不引入向量库用步骤序列的 Jaccard 相似度就够import re def normalize_step(step: str) - str: 归一化替换同义词、去掉标点空白降低无关干扰 step step.replace(登录, 登录).replace(登陆, 登录) step re.sub(r点击|按下|点一下, 点击, step) step re.sub(r[\s。、,.:;], , step) return step def jaccard_similarity(steps_a: list, steps_b: list) - float: if not steps_a or not steps_b: return 0.0 set_a set(normalize_step(s) for s in steps_a) set_b set(normalize_step(s) for s in steps_b) inter len(set_a set_b) union len(set_a | set_b) return inter / union if union else 0.0 def dedup_cases(cases: list, threshold: float 0.85) - list: result [] for case in cases: steps case.get(steps, []) is_dup False for existing in result: if jaccard_similarity(steps, existing[steps]) threshold: is_dup True break if not is_dup: result.append(case) return result逻辑说明Jaccard 计算的是“两个步骤集合的交集占比”值越接近 1 越相似。threshold 取 0.85意思是有八成五的步骤是重合的就认为是重复用例。这个阈值对 10 步以上的用例比较稳步骤太少时容易误判比如一个三步的正例和一个三步的反例步骤完全一样期望结果不一样Jaccard 会打出 1.0 的分数但它们明显不该被删。所以判重只看 steps但最终补偿要结合 expected。对策是加一个合并函数steps 完全一样、expected 不同的用例不该删而应该合成一条参数化用例。示例def merge_by_expected(cases: list) - list: groups {} for case in cases: key tuple(case[steps]) prep case.get(precondition, ) key (prep, key) groups.setdefault(key, []).append(case) merged [] for (prep, steps), group in groups.items(): base group[0] extra_expected [c[expected] for c in group[1:] if c[expected] ! base[expected]] if extra_expected: base[expected] base[expected] .join(extra_expected) base[type] combo merged.append(base) return merged参数说明合并时把 precondition 也放进 key关键原因同样的步骤在“已登录”和“未登录”前置条件下是完全不同的两条用例不能合并。合并后把 type 改成 combo是为了让框架执行时知道这条用例有多组期望结果需要参数化跑。这个细节容易踩坑我见过有人合并后只保留第一个 expected结果反例被正例吞掉看起来用例数少了实际是测试覆盖悄悄缩水了。到这里你已经能生成覆盖面相对均衡、无明显重复的用例集。但这套链路真正开始考验人的是接入 API 之后的各种不稳定。下一章讲我在这条链路上踩过的五个坑每一个都是真金白银换来的血泪经验。5. 智能用例生成避坑指南DeepSeek API 接入中的 5 个常见问题大模型生成用例最大的特点就是不可控。前面几章的设计都是在和不可控做对抗但有些坑光靠 Prompt 设计绕不过去必须在工程层兜底。这一章写五个我实际遇到的问题每条按现象、原因、解决三步讲。5.1 响应被截断输出长度限制与分段生成现象生成的 JSON 到一半就断了json.loads 直接抛 “Expecting value”。第一次遇到我还以为是温度太高模型疯了后来看返回内容明显是 max_tokens 不够用。原因一次让模型生成 40 条完整用例每条带步骤、测试数据、期望结果token 消耗早就超过了单次返回上限。模型不是不想写完是写到字数上限被强行截断。解决分两层。第一层是第 3 章的 batch_size 控制每批少生成一点第二层是写一个“检测残缺 续写”的兜底函数。检测逻辑很简单JSON 解析失败时尝试把已生成的文本作为前缀拼上“继续输出剩余 JSON不要重复已输出内容”再调一次def generate_complete_cases(prompt, max_retries2): text call_deepseek(prompt) for _ in range(max_retries): try: return json.loads(text) except json.JSONDecodeError: text call_deepseek( 继续输出上一条 JSON 的剩余部分只输出 JSON 数组内容不要复述前面内容\n text[-500:] ) raise RuntimeError(连续续写失败请减小 batch_size)参数说明续写时补上text[-500:]是为了让模型知道从哪里接着写但只给末尾 500 字符避免把整段重复内容再算一遍 token。这个兜底能救回一部分截断但不是万能的如果连续两次续写都失败最有效的做法是改小 batch_size而不是继续硬凹。5.2 幻觉用例不存在的按钮和数据现象生成的用例里出现需求文档里根本没有的功能比如订单系统里冒出一个“一键迁移订单”操作步骤里引用了一个“订单状态重置按钮”实际上是系统里不存在的东西。原因需求文本没有给出页面元素清单和字段范围模型在开放性生成时用训练数据里的常识补全了“该有的功能”。这是大模型幻觉在测试场景中的典型表现不是模型坏了而是你给它的约束不够。解决在 Prompt 里强制加入“可用操作清单”和“字段范围表”并明确写“只能使用以下元素”。具体做法是把结构化 JSON 里增加一个 allowed_ops 字段把系统里真实存在的接口、按钮、字段名列进去。格式类似allowed_ops: [创建订单, 取消订单, 查询订单, 修改收货地址], field_ranges: {price: 0.01-999999.99, coupon_id: 数字可空}然后在 CASE_GEN_PROMPT 里把“不得新增任何元素名”这句话变成硬约束放在用户消息末尾而不是埋在系统消息里。模型对近处指令的遵从度明显高于远处的声明。这算是我踩坑换来的经验靠 Prompt 中间一句“请使用正确的元素”是不够的元素白名单本身必须进结构化 JSON。5.3 延迟与重试超时、限流、退避策略现象几十个用例批量生成时偶尔会有单次请求 pending 四五十秒不返回或者 HTTP 429。跑一次全量生成总有几条因为超时失败整个脚本中断。原因长 prompt 加 4000 token 输出单次推理时间长是正常的并发请求一多限流就来了。请求失败本身不意外意外的是我们没写重试导致一次失败拖垮整批生成。解决必须加指数退避重试并且区分可重试和不可重试的错误。HTTP 429、502、503 可以重试401 认证失败、400 参数错误重试多少次都没用。下面是简化版重试逻辑import time def call_with_retry(prompt, max_retries3, base_delay2.0, **kwargs): last_exc None for attempt in range(max_retries): try: return call_deepseek(prompt, **kwargs) except requests.exceptions.HTTPError as e: status e.response.status_code if status in (401, 400, 422): raise if attempt max_retries - 1: raise delay base_delay * (2 ** attempt) print(fHTTP {status}第 {attempt 1} 次重试等待 {delay}s) time.sleep(delay) except requests.exceptions.Timeout: if attempt max_retries - 1: raise time.sleep(base_delay * (2 ** attempt)) raise RuntimeError(重试失败)参数说明base_delay2.0 是指第一次重试等 2 秒第二次 4 秒第三次 8 秒。指数退避的核心是别把重试请求同时打进服务端造成雪崩。timeout 那段单独捕获因为超时不一定真的失败了可能只是响应慢重试的代价比直接放弃小。我习惯把 max_retries 压到 3重试次数太多最后一批结果跑完了前面的缓存已经被冲掉工程上不值得。5.4 成本控制Token 消耗与缓存现象跑完一轮全量生成打开账单发现消耗比预期多不少。一查同一份需求文档在调试 prompt 时反复提交了十几次每次都是全量 token。原因成本主要烧在输入 token 上。调用一次生成需求文本几千 token 进去模型输出同等量级回来输入输出各计费。调试 Prompt 时以为自己在调一句话实际每次都在为完整需求文本付费。解决加一层语义缓存。同一份需求文本不管跑哪个维度结构化结果都是一样的没必要每次重新抽取。实际操作用需求文本的哈希值做缓存 keyimport hashlib cache {} def cached_generate_case_set(requirement_text: str): req_hash hashlib.sha256(requirement_text.encode(utf-8)).hexdigest() if req_hash in cache: return cache[req_hash] cases generate_case_set(requirement_text) cache[req_hash] cases return cases参数说明这个方案简单粗暴进程内字典缓存适合脚本场景。如果要落到工程级把哈希 key 和结果存到 Redis 或本地 sqlite。重点是把结构化抽取结果单独缓存因为它是后续所有维度生成的公共依赖缓存一份能省下五分之四的输入 token。调试 Prompt 时先用截断的需求片段调通格式再跑全量也是省钱的习惯。5.5 格式漂移JSON 解析失败现象模型偶尔会在 JSON 外面包一层 markdown 代码块开头是json结尾是或者 JSON 内部多了一个逗号。这类输出用标准 json.loads 会直接失败但内容本身是完整的。原因模型在训练数据里见过大量代码块示例生成时模仿了那种格式。这和模型能力关系不大纯粹是输出风格漂移每天都有概率出现。解决写一个容错解析函数第一步把文本里的 markdown 代码块标记剥掉第二步裁剪出第一个{到最后一个}之间的内容第三步再尝试 json.loadsdef robust_json_loads(text: str): text text.strip() if text.startswith(): text re.sub(r^[a-zA-Z]*\\n|$, , text) start text.find({) end text.rfind(}) if start -1 or end -1: raise ValueError(找不到 JSON 对象边界) candidate text[start:end 1] try: return json.loads(candidate) except json.JSONDecodeError: candidate candidate.rstrip(,) candidate re.sub(r,\\s*([}\\]]), r\\1, candidate) return json.loads(candidate)逻辑说明正则把,后面紧跟右括号或中括号的多余逗号去掉处理的是模型最爱犯的“最后一个元素后面多逗号”问题。这个方法不是银弹如果模型输出中途丢失字段裁剪也没用会走到 ValueError。所以 robust_json_loads 要放在前面 5.1 的续写逻辑之前先做格式清洗清洗不掉再续写最后还不行就丢弃这条结果并记录日志。丢几条用例不可怕可怕的是整个流程因为一条脏数据中断。这五个问题基本覆盖了 API 接入层的主要雷区。解决了它们生成链路才算真正稳定。最后一章把这批用例接进自动化测试框架形成一个能迭代的闭环。6. 把生成的用例接进自动化测试框架适配层与反馈闭环6.1 用例格式与框架的适配层生成的 JSON 用例是数据不是可执行脚本。接进 pytest 这类框架时要写一个适配层把用例字典翻译成可调用的测试函数。我的做法是做一个 builderdef build_test_function(case: dict): def test_case(): for step in case[steps]: # 每个 step 映射到 API 调用、断言或页面动作 run_step(step, case.get(test_data, {})) assert check_expected(case[expected]) return test_case逻辑说明适配层不关心用例是怎么生成的只关心 steps 和 expected。这样生成管线换模型、换 Prompt 都不会污染测试框架。test_data 单独传是因为同一个步骤在参数化用例里会有多组数据拆开更干净。6.2 用上一轮的失败反馈做第二轮生成把执行结果做成反馈喂回给模型生成回归用例或修正原用例。这是我的习惯每条失败用例跑完把断言错误摘要和对应步骤拼成反馈 prompt让模型补一条“针对该失败场景的回归用例”。跑完第一轮只是开始真正让用例集越用越准的是这个反馈回路。REGRESSION_PROMPT 以下是执行失败的用例 {case_json} 失败信息 {error_summary} 请生成一条针对该失败场景的回归用例要求覆盖相同路径但增加断言强度。 时间久了你会养成一个习惯每次跑完测试先存一份失败摘要到固定目录下一轮生成前把它作为上下文传进去。不要嫌麻烦这个动作能让用例集从“通用”慢慢长出“业务敏感”。希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/21 8:42:29

Agent技能系统设计:从工具堆砌到可复用技能架构

提到“agent-skills”这个词,很多接触过大模型应用开发的人第一反应是:哦,给Agent加一堆tools(工具),让模型能调用外部能力。但如果一个项目被命名为“agent-skills”并且被认真对待,它往往做的…

2026/10/21 8:42:29

43寸户外落地触摸一体机:展馆查询终端的选型、安装与运维

做展馆类项目这几年,我经手过不少查询终端,KIHU快狐这台43寸户外落地触摸一体机算是其中很有代表性的一类形态。很多第一次做展馆、园区或游客中心的人,听到“户外”“落地”“触摸”几个词就直奔尺寸和外观,结果装完才发现真正的…

2026/10/21 8:42:29

自动增益控制放大器设计详解:从VCA810选型到MSP430闭环实现

简介:2014年全国大学生电子设计竞赛H题《自动增益控制放大器》设计报告,面向电子竞赛参赛者、电子信息类专业学生及工程技术人员,系统讲解AGC放大器从方案论证到硬件实现的全过程。系统输入信号经程控放大器调理归一后送入VCA810,…

2026/10/21 12:25:17

电赛无线传输信号模拟系统:零中频架构与信道模拟工程实现

简介:这份资源是2024年全国大学生电子设计竞赛C题「无线传输信号模拟系统」的江苏省第一名完整方案,面向备赛电赛的本科生、研究生及电子设计爱好者,尤其适合需要攻克DDS信号生成、调幅波合成与多径传输模拟等难点的中高级选手。方案以STM32F…

2026/10/21 12:25:17

RAG从入门到实战:为大模型构建外挂知识库的完整指南

1. 先说结论:RAG是什么,一句话能不能讲清楚 如果你在技术圈泡过一阵子,肯定绕不开RAG这个缩写。全称Retrieval-Augmented Generation,中文叫检索增强生成。我见过太多人一解释RAG就搬出概念图、向量数据库、Embedding模型、相似度…

2026/10/21 12:25:17

Qwen开源多模态嵌入模型:图文统一语义空间与RAG落地实践

Qwen家族这波更新里,真正让我兴奋的其实不是又大一号的对话模型,而是那款开源多模态嵌入大模型。做过多模态检索和多模态RAG的朋友应该都有同感:向量检索这几年在纯文本侧已经卷得非常成熟,但图、文混在一起想用一个统一语义空间做…

2026/10/21 12:25:17

OpenClaw部署实战:从移动云到Windows本地,零基础玩转AI技能插件

如果你刷到过别人用AI助理自动整理资料、定时跑脚本、随手调用各种工具,但一直觉得那是“高玩专属”,那这篇就是写给你的。OpenClaw(也叫Clawdbot)是一个开源的智能体运行框架,简单说就是把大模型从一个“只会聊天的对…

2026/10/21 12:20:15

Flutter鸿蒙跨端开发:async/await与图片下载实践

做 Flutter 鸿蒙跨端开发,几乎绕不开一个场景:从网络拉取一张图片,加载出来、展示给用户,甚至保存到本地。图片下载四个字看起来简单,可真到了鸿蒙设备上,异步模型、网络请求、缓存策略、系统权限会全部凑到…

2026/10/21 4:53:08

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/21 0:00:35

交通流仿真实战:IDM跟驰与MOBIL换道模型参数调优与避坑指南

简介:这份资源是面向交通工程学习者与Python开发者的微观交通流仿真项目,核心实现智能驾驶模型(IDM)下的车辆跟驰与换道行为,可用于理解速度、密度与流量之间的动态关系,适合具备Python基础、希望深入交通模…

2026/10/21 0:00:35

揭穿智能体表面顺从:用追踪代码重建任务执行确定性

1. 表面顺从不是智能体的“礼貌”,而是任务执行链路上的隐性断点最近在调试一个跨平台长周期任务调度系统时,我反复遇到一种令人困惑的现象:智能体在用户指令发出后,几乎秒级响应“已收到”“正在处理”“请稍候”,UI上…

2026/10/21 0:00:35

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑