先冻结问题,后运行成绩
前六章已经有从资料到工具、持久化、恢复和结果验证的完整路径,本章让同一入口在固定任务集上运行。data/tasks.jsonl 每行定义原任务、预期终止状态、预期业务效果数,以及可选故障或本地policy。预期标签是测试规范,实际状态、库存、引用和调用数由程序执行产生。二者不能混淆:手写一列expected并不等于已经成功,只有执行后把独立观察与规范比较,才形成结果。项目run.py demo逐条创建独立数据库,避免前一任务库存影响下一条。
固定集含十七任务:正常资料查询、正常预留、缺货、无写权限、无命中、歧义、恶意资料附注、读取暂时失败、提交后丢回复、提交后中断、零预算、过短预算、零重试、本地拒答策略、未知工具策略、提交后失联且零重试、恰好四次调用的预留。每条都走同一导入器与Runner,不是专门为测试写一个直接返回status的替身。local-abstain与invalid-tool使用真实JSON策略适配器,其他任务默认规则;HTTP适配器另由真实本机服务器测试集成。
任务成功的谓词必须与需求一致
对任务i定义通过指示 ,要求实际状态等于预期状态、引用检查通过、实际ledger效果数符合规范,并且有写入时库存扣减与回执一致。每条还执行事件重放并核对快照。正常任务reserved应有一条效果,denied或insufficient应没有,lost-reply-no-retry则预期客户端重试耗尽却已有一条效果。这种任务不是“系统失败就强行算成功”,而是在验收错误边界:它必须如实暴露未确认状态和已提交事实,不能谎报零效果。
总体任务符合率是通过数除以总数,表示这份冻结测试规范下的行为一致性。它不是语言智能分数,也不估计互联网未知请求的成功概率。任务按我们选择的机制覆盖构造,不是从真实用户分布独立抽样,十七分之十七不能外推“任何需求都能完成”。正式报告同时按状态与机制分组,保留每条调用数、效果数、库存、支持与重放结果,让读者看到到底完成了什么。
完整算例一:同样终止,不同业务含义
比较retry-zero与lost-reply-no-retry。两者都以retry_exhausted结束,但前者在search执行前遇暂时故障,calls为一、ledger为零,库存三;后者前三个读工具成功,reserve提交后失联,calls为四、ledger一、库存二,客户端尚无reserve观察。若评估只看status,两者看似相同,业务效果却相反。项目报告保存效果数和库存,分别与预期零和一核对。这个算例使第四章的未知确认边界真正进入完整任务集,而非只停在文字讨论。
再比较zero-budget与short-budget。零预算连search都不调用,calls为零;两次预算的预留任务已经取得search和document观察,之后停止。两者都budget_exhausted且不写库存,但保存的信息不同,恢复与排查价值也不同。把所有非reserved状态统称失败会掩盖这种区别;把所有按预期终止都称“业务完成”同样错误。报告名称采用“符合固定测试规范”,明确正常拒绝和故障边界也在其中。
完整算例二:总体通过掩盖安全失败
构造十七个任务,其中十六正确、一个越权写入却仍返回denied。只按status可能得到十七分之十七;加入ledger检查就只有十六分之十七,并且安全门槛必须失败,而不是因为百分之九十四点一还不错就交付。若把安全任务权重降低,总分仍可提高,但那不能消除越权事实。因此最终判据先检查关键不变量没有失败,再看功能覆盖和调用成本;安全约束不是可以用平均分补偿的偏好。
rows=[{'status_ok':True,'effect_ok':True} for _ in range(17)]
rows[-1]['effect_ok']=False
status_rate=sum(r['status_ok'] for r in rows)/len(rows)
joint_rate=sum(r['status_ok'] and r['effect_ok'] for r in rows)/len(rows)
assert status_rate==1 and joint_rate==16/17
assert not all(r['effect_ok'] for r in rows)
print(status_rate,joint_rate,'safety gate FAIL')故障注入与测试替身要区分
故障注入是在真实路径的某个明确位置制造异常。search_transient在读取前抛一次暂时错误;lost_reply在库存及ledger提交后抛异常;crash_after_commit让进程驱动中断而保存pending。它们借助数据库faults表确保“只触发一次”跨恢复仍成立。若只在最外层返回一份假错误结果,没有真实提交和恢复,就没有测试危险空窗。项目的效果检查可以抓出这样的假模拟:库存与账本必须符合故障发生位置。
默认工具和策略是确定性的,所以相同初始数据库、任务和故障配置应得到相同语义结果。事件摘要也由规范序列化生成,不引入当前时间或随机调用编号来制造无关差别。实际HTTP契约测试使用动态端口,但端口不属于业务状态。CPU耗时只用于测试过程记录,不作为任务能力分数。本课没有远程LLM采样、成本或延迟评估,若换成随机策略,须增加种子、重复、错误分布与请求预算,而不能沿用确定性的一次通过作为概率保证。
恢复测试需要比较整个对象
单元测试在多个停止点执行部分任务,再恢复并与连续运行的完整状态比较;提交后崩溃例还检查pending、累计调用五次、ledger一条和库存二。仅比较最终status会漏掉重复扣减,仅比较库存会漏掉错误引用或错误任务身份。重放核验又从另一条路径检查事件链与快照一致。恢复的目标不是每次尝试数都与无故障运行相同,而是合法边界中业务结果一致,并准确记录额外尝试;故障后多一次调用是应保留的成本。
支持性检验使用实际生成的 claims,不手工填一组恒真的引用。text 或 SHA 突变必须失败,正常摘录应通过。完整性另由原件构造的 required_claims 集合核验,空、缺项和重复声明均不能让资料正例通过。当前范围是精确摘录器,不把相关性、开放语义支持或现实真值合并成一个指标。
开发失败与未测项也要留下
首次运行本机HTTP契约时,环境禁止绑定回环端口,出现PermissionError。这是运行环境阻断,不是HTTP协议已通过,更不是远程服务失败。取得允许本机测试的执行权限后,真实HTTP任务完成;development-failures.json保留原错误与处理。这样读者能区分功能缺陷、环境限制、预期故障注入和最终通过。修复后不必在主表继续算失败,但不能删除历史并宣称从未遇到限制。
远程语言模型明确NOT RUN,生产多进程任务所有权、分布式事务及动态资料版本未实现。评估应把这些列为范围外或未运行,不填写零分或通过率,因为没有对应运行事实。若将课程项目接入外部模型,应保留当前固定集作为执行协议回归,再新增真实用户任务和模型特有失败;新成绩必须绑定模型版本、policy配置与源码,不能直接继承规则策略的十七项通过。
两个独立评价层
第一层是端到端固定任务,覆盖资料导入到最终结果的连续链。第二层是局部性质与故障单元测试,专门检查布尔类型、未知字段、任务身份、重复键、载荷冲突、过期版本、篡改链、越权、引用突变、JSON与HTTP替换。端到端通过可能漏掉某个未出现输入,局部通过也可能没有把模块接起来;两层同时通过才支持当前可运行范围。评估报告保留逐项结果,而不是只有一个总绿色图标。
练习与项目增量
TRY IT YOURSELF
基础:总体符合率
十七任务有两条status正确但effect_count错误,其余全部正确。状态符合率与联合符合率各是多少?
提示 1
提示 2
对照参考解答
TRY IT YOURSELF
进阶:故障位置
怎样区分“提交前抛错”的测试与“提交后丢回复”的测试?
提示 1
提示 2
对照参考解答
TRY IT YOURSELF
挑战:外推边界
规则policy在固定十七任务全通过,能否称新接入模型的智能体成功率100%?给出合理评价方案。
提示 1
提示 2
对照参考解答
本章交付是run.py demo产生的evaluation.json与源码收据,以及tests.py逐项记录。最后一章从独立目录复跑并冻结同一个版本,给出可以审计的最终报告。项目完整性由资料、状态、工具、持久化、恢复与评估的连通路径证明,而不是由任务条目多少或讲义篇幅证明。