我维护的智能体框架带一个 Electron 图形界面,渲染进程与网页终端共用。昨晚它一晚上坏了两次,第二次故障正是第一次修复造成的。两次都没有报错。第一次我能解释,第二次才是真正值得记下的——它暴露了第一次修复的测试套件看不见的东西,而最终修复是一个核对现实的守卫,而不是核对守卫自己的算术。
第一次故障:浅色主题回退
![]()
React 终端用 CSS 自定义属性做主题,但迁移过程中有一块把深色调色板的十六进制色值直接硬编码进了组件样式。浅色模式下界面看起来不对:浅色卡片上压着深色文字,对比度很差,完全是半成品主题重构的形状。修复方式是把所有地方都改走主题变量,这个版本以 v0.2.84 发布。这部分很直接。
第二次故障:修复有个洞,而且洞是隐形的
主题变量修复落地之后,第二轮损坏出现了:任务表单背景渲染成透明,文件标签悬停失效,徽章字号和圆角都不对。没有任何东西抛出异常。没有控制台报错,没有崩溃,没有失败的测试。原因是这次修复用到了四个变量——--fs-small、--radius-sm、--bg-1、--bg-hover——它们在 tokens.css 里根本不存在。一个没有回退值的裸 var(--x) 不是错误。在计算值阶段,这个声明会变成无效,属性被当作从未指定过。元素直接回落到默认值——透明背景、没有悬停样式、默认字体度量。未定义 CSS 变量的失效方式就是沉默。
这是我想保留的部分:这个 bug 不是一个错误的值,而是一个从未存在过的值,却被当作存在来消费。测试通过,是因为测试断言的是行为,而那个行为就是“浏览器对无效声明所做的任何事”。
核对“已定义”的守卫
修复是一个守卫,而不只是一个值:一个静态测试,遍历渲染进程里的每个 CSS 文件,断言每个裸 var(--x) 都在 tokens.css 中定义——每个主题块都要查,浅色默认加强制、深色媒体查询加强制。第二条规则断言 tokens.css 之外不存在深色调色板的十六进制色值,并且去掉注释后再检查。负向状态也验证过:这个守卫在修复前的 tokens 上会失败,在修复后的 tokens 上会通过。从现在起,未定义变量就是一次红色构建,而不是一个透明表单。
元故障:核对算术、而不是核对现实的守卫
修这个的时候,我们又发现第三处静默漂移。项目文档里列着渲染进程测试用例的逐文件计数,这个计数已经从 445 漂到了 448。文档计数守卫验证的是每一行内部的和——各部分加起来等于标题数字——但从来没有把总数拿去和测试运行器实际执行的数量比对。pytest 的 CI 任务里没有 node_modules,所以 vitest 在那里从不运行;没有任何东西把这个数字拿去和现实核对。修复是一个静态守卫,按源文件统计测试用例定义数,并断言总数等于实际执行的数量。
三个故障共享同一个形状:系统里有一个数字或一个值,它被另一个地方引用,但引用方只检查自己内部的算术,不检查外部现实。第一次是主题变量被硬编码绕过,第二次是变量名被消费但从未定义,第三次是文档计数只做内部求和。前两次是 CSS 的静默失效,第三次是文档的静默漂移。真正能拦住它们的,不是更聪明的断言,而是把断言的对象从“我算得对不对”换成“现实里到底有没有这个东西”。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.