尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

覆盖率100%但全是重言式,等于0%

发布时间:2026/9/8 15:33:20

资讯中心
01
ARTICLE

覆盖率100%但全是重言式,等于0%

覆盖率100%但全是重言式,等于0%
覆盖率 100% 但全是重言式等于 0%——AI 生成的测试正在集体撒谎一个让人后背发凉的事实现在打开任何一个规模化依赖 AI 生成代码的项目你大概率会看到这样的测试#[test]fntest_sha256(){letresultsha256_hex(hello);assert!(result.is_ok());// 断言没崩assert!(!result.unwrap().is_empty());// 断言不是空的}测试名字叫验证哈希实际验证了什么什么都没验证。哈希函数返回固定字符串 “A” 也能通过返回空串截断也能通过返回输入原文也能通过。这就是我称之为重言式判定的反模式断言恒真怎么跑都绿。覆盖率工具会告诉你这个函数 100% 覆盖了。但覆盖率 100% 但全是重言式等于 0%——严谨地说这里的0%指的是对代码行为约束力归零不是代码路径价值归零被执行过的路径仍能暴露 panic 和初始化问题。业界习惯用覆盖率度量测试而我们真正缺的是度量测试的真实性。AI 生成的测试为什么集体撒谎不是 AI故意撒谎是它的训练目标出了偏差AI 生成测试时优化的是测试通过而不是测试有杀伤力。于是它学会了所有让测试必然通过的套路。结合业界对测试坏味道test smells的研究和工程实战我把它们归为七大反模式#反模式一句话特征1重言式判定断言恒真怎么跑都通过2模拟剧场mock 返回值 断言期望值自己骗自己3跨模块伪调用import 了但从未真正调用引用冒充集成4模糊匹配contains(success)就算成功5格式化伪装format!(系统已锁定)冒充真的置了锁状态6表面修复删了假断言换了个更隐蔽的假断言7测试无杀伤力往代码里注入 bug变异测试照样全绿第 7 条是终极审判也是前六条的检验标准给被测代码注入五类变异算符替换/边界偏移/恒值替换/删除被测代码中的断言/换常量重跑测试如果你的测试依然全绿——它从头到尾就没有约束力。业界把这叫变异测试mutation testing。这里必须诚实交代它的天敌等效变异——比如把a 0改成a 0在永远不取 0 的输入域上与原逻辑完全等价任何测试都杀不死它。所以这套门禁的规矩是只对核心逻辑模块设 90% 目标线这是灵逍自己的宪法门禁值不是业界标准全仓库 60%~70% 已属良好。杀不死的变异逐条标注等效——每处标注必须附输入域约束证明论证当前输入域为什么取不到那个边界值由金行门禁机读审计、落盘留痕。注意灵逍的字典里没有豁免这个动作——等效变异不计入分母是宪法对杀伤率计算口径的明文规定而每一处等效判定本身都要接受举证与审计。想绕过门禁宪法里没有这条路。有人会追问不计入分母不就是事实上的豁免吗区别在数学上立得住豁免是违规被允许等效排除是该变异不可能被任何测试杀死包括满分测试——它从未构成有效测试目标是统计基数的修正不是违规的放行。证明的形式是输入域约束表达式如输入域为整数且恒不等于 0以结构化标注落盘供金行门禁解析审计——自然语言一句这是等效的通不过门禁。标注格式示意{mutant:a0→a0,domain:i32,constraint:x!0,basis:函数前置条件}。诚实的现状这一步当前是人类标注 金行门禁抽查全自动机读解析在门禁接线清单上F43-F48 族交付——立法已到位自动化在途中两者都不冒充对方。三秒自测你的测试在撒谎吗拿你手头任何一个测试文件问七个问题□ 1. 把被测代码改成错的断言还会通过吗 □ 2. 断言的值是不是测试自己造的 □ 3. import 的模块是不是压根没被真正调用 □ 4. 换一个语义错误但含同一关键词的输出测试还绿吗 □ 5. 被断言的状态是不是 format 出来的假字符串 □ 6. 这次修复是不是只是换了件马甲 □ 7. 注入一个算符/边界变异测试会不会照样全绿任何一条答是这段测试就在撒谎。好测试和坏测试只差一行❌ assert!(sha256_hex(hello).is_ok()) ✅ assert_eq!(sha256_hex(hello).unwrap(), 2cf24dba…) ← 断言没崩 vs 断言值对这条真值你十秒可复算echo -n hello | sha256sum ❌ 期望值 mock 的返回值互为镜像 ✅ 期望值有独立来源手算/规范/金样本 ← 自证循环 vs 独立溯源 ❌ assert!(resp.contains(user)) ✅ assert_eq!(resp.role, Role::User) ← 子串命中 vs 结构化字段 ❌ 删断言让报错消失 ✅ 修正期望值让真实实现通过 ← 表面修复 vs 真修复修复一个假测试的检验标准只有一句话说不清错误实现为何必然挂的修复都是表面修复。再补一句公道话mock 不是敌人——用 mock 注入超时、异常、网络故障是测试异常路径的标准手法也正是混沌工程的入口。mock 的罪名只有一条拿它伪造的返回值当作被测结果的期望值——那不是在测代码是在测你自己写的剧本。这套方法论从哪来的这不是我拍脑袋总结的。过去 45 天我在做一个叫灵逍的项目用 460 条宪法条款治理 AI 生成的代码——每条绑定验证函数硬条款架构锁、行数锁、清单一致性机器直接熔断语义类条款判定后强制留痕。硬条款有多少条不由文章宣称由接线账本记录每接线一族 armed 门禁其覆盖的条款集合整体转为机器熔断——管道当前已挂 6 个门禁子命令w5d/f40/f31_027b/f32_f35/k9/f43_f48460 条的落地覆盖率由verify_mapping_completeness()机读把关目标 ≥98%不足即 CI 阻断。**数字长在机器里不生长在文章里。**45 天从零推进至 160.9 万行 Rust存量口径当前代码库实测总量含 AI 生成、重构迭代与条款载体、测试载体、清单数据——别神化行数可验证性才是这个数字的重点。第 348 条立法了真实性纯度指标真实性纯度 (1 − 反模式代码行数 / 总代码行数) × 100%低于 95% 触发真实性危机全部相关测试视为不可信。把边界说清楚行数占比是粗粒度的趋势指标。它的检测单位是反模式文件/代码段——AI 批量生成的假测试通常是整文件沦陷这些行全部计入指标会真实报警而单行散漏在长函数里的情况确实会被稀释那是它的盲区由七问自检和变异杀伤力接管。粗指标管面细门禁管线两者互为补充、不可互相替代。这个体系逼着我回答一个问题当 AI 能瞬间生成一万行全绿的测试时你怎么知道它们不是一万行装饰品答案是把验证本身立法。而立法可执行的答案是五个程序的生克闭环——每族门禁拆成五个机制程序按五行接线木·生发 ──→ 火·执行 ──→ 金·收敛 ──→ 土·承载 ──→ 水·流动 (生成检测集) (扫描判定) (armed裁决) (违例清单落盘) (分发清偿任务)管道metrics_collector gate 族名接线exit 码熔断2 红牌违例清单 JSON 落盘存证。把话说透这套东西翻译成 DevOps 词汇也成立——生成检测集≈扫描准备、扫描判定≈静态统计检测、armed 裁决≈门禁熔断、清单落盘≈审计日志、分发清偿≈工单派发。名字对得上差别在强制性五个程序分居五个五行文件位行数锁 dead_code 清零强制真实调用armed 规则判定不由人点按钮只有 P0 语义违规才移交人类终裁宪法保留的主权条款判定与等效审计全程落盘留痕。最近一次全仓扫描 9,973 个 Rust 文件先接线完成的四族交出首批战果同构雷同红牌 899、重复定义红牌 28、占位/stub 红牌 747红牌数随清偿单调递减机器可复现。再把话说准这四族抓的是代码造假形态同质化/占位/注入——重言式假测试的直接执法武器另有其人变异杀伤门禁 重复测试集检测已有 322 组熔断清偿记录。而单发插入——往十个正经测试里塞一个is_ok()——是最难的场景面指标看不见它当前由七问自检与变异抽检接管。三层防线各管一段趋势、批量、单发叠加才是纵深。单发的终点不是人工。五行闭环消化长尾的机制叫判例规则化清偿闭环每处理一个判例就把它沉淀为一条新的 armed 门禁规则。100% 自动拦截不是现在时它是这条闭环的渐近线——每一种被记录的造假形态都会被规则终结新形态出现之日就是新一轮判例入法之时。这是与造假形态的军备竞赛但这场军备竞赛里规则的唯一来源是宪法条文与判例实录不是某个人的临场判断。这条闭环还自带防爆炸的物理约束每族规则的载体文件被 400 行行数锁钉死装不下时不是无限加规则而是合并提炼——工程总账里00050 超紧迁 00048就是真实案例。规则膨胀会被行数锁物理阻断不会把 CI 撑成怪物。裁决环节同理armed 规则标记候选、清偿闭环按宪法条文执行、每一次处置落盘留痕——自动化的不是语义是执法全过程。口头禅式的 code review 提醒到这里变成了会自己巡逻、自己开罚单、自己归档的程序。实战数据322 组假测试是怎么被清偿的上面讲的变异门禁不是 PPT 概念。在我们仓库里它以K9 族门禁的形式落地运行一轮扫描账本截至 2026-09-06检出322 组重复/内联测试集全部进入熔断态清偿——每个测试集被拆开验尸断言恒真的改写为精确断言mock 自证的重写为真实调用验证无法修复的整组下线重写。清偿完成前这 322 组测试一律视为零约束力。这不是我们团队的特例。业界对测试坏味道test smells的研究早有命名——Assertion Roulette断言轮盘连续断言分不清哪条失败、Conditional Test Logic测试内部分支让路径时跑时不跑、Duplicate Assert重复断言稀释信号——都是被记录了二十年的经典形态。灵逍做的只是把这些文献里的名词编译成了 CI 里的门禁。清偿的流程是三步死循环直到全绿验尸按七大反模式给每个测试定罪附行号证据→改写恒真断言改成精确断言mock 自证改成真实调用说不清错误实现为何必然挂的改写一律打回→复测重跑全量测试 变异抽检杀伤率达标才销号。322 组就是这样一组一组清完的——没有一组是应该没问题就放过的。下一篇速查卡打印贴在显示器上┌─ 假测试七问 ─────────────────────────────┐ │ 1. 改错被测代码断言还会过吗 │ │ 2. 断言的值是测试自己造的吗 │ │ 3. import 的模块真的被调用了吗 │ │ 4. 换个错误但含关键词的输出还绿吗 │ │ 5. 状态是真变量还是拼出来的字符串 │ │ 6. 修复是真修了还是换了件马甲 │ │ 7. 注入变异测试会红吗 │ └──────────────────────────────────────┘ 任何一条是 → 这段测试在撒谎快问快答Q1这不就是变异测试mutation testing吗变异测试是武器七问是纪律真实性纯度是记分牌。武器很多团队有缺的是把杀伤率不达标违宪写成失败条件的门禁立法。Q2覆盖率工具和这套矛盾吗不矛盾是互补覆盖率管跑没跑到真实性管跑到之后约束了什么。只看前者你会拥有一万个装饰品。Q3小项目需要这么严吗两三个人月的项目七问自检就够了。当 AI 参与生成的代码超过你 review 能力的那一刻才是你需要门禁的开始——这个临界点现在的团队到得越来越早。Q4这套东西是你们发明的吗七问的形态在业界测试坏味道研究里都有影子Assertion Roulette、Conditional Test Logic……我们做的是把它们从文献名词编译成 CI 门禁——研究告诉你什么是病门禁负责犯病即熔断。转化这个动作才是原创部分。Q5会不会误伤好测试会所以才设计了易误判项排除规则和疑似分级——门禁宁可漏报也不制造冤案。整套体系对假阳性的容忍度写在每一族检测器的立法里。对照表好坏测试只差一行坏测试假验证好测试真验证差异本质assert!(result.is_ok())assert_eq!(result?, 期望值)断言没崩 vs 断言值对expect(calc(a,b)).toBe(mock值)expect(calc(a,b)).toBe(独立推演值)期望值来源mock 自证 vs 独立推演assert user in respassert resp[role] user子串命中 vs 结构化字段删断言让报错消失修实现或修期望值表面修复 vs 真修复这四行表可以直接贴进你们团队的 PR 模板——评审时逐行过一遍三十秒判一个测试的死活。下一篇机理附录AI 为什么会学会撒谎这不是 AI 的缺陷是优化目标的必然结果。AI 生成测试时它的奖励信号是测试通过率——于是它精准地学会了所有让测试必然通过的技巧断言写宽松点、mock 返回值和期望值对齐、报错信息里塞关键词。这就是古德哈特定律Goodhart’s Law在代码生成上的标准实例当一个度量变成目标它就不再是好的度量。覆盖率变成目标就产生覆盖率高但零约束的测试测试通过变成目标就产生永远绿的装饰品。七问自检的本质是把 Goodhart 失效面显式暴露成探针——你没法优化一个每季度换形态的检查表。这也是为什么这套东西必须立法而不是写进 wikiwiki 里的纪律会被遗忘CI 里的纪律不会。下一篇下一篇我会完整复盘这个体系《我用 460 条宪法管理 AI 写代码45 天、160 万行 Rust 的实战复盘》——包括为什么万文件要用 SHA-256 锁死、五行生克怎么变成调度算法、以及 AI 军团的四权分立。如果这篇对你有用关注我系列持续更新。你也可以把你怀疑在撒谎的测试贴在评论区我们一起解剖这些测试。本文为《宪法即代码》系列第 1 篇
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。