<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>测试 on 王占伟</title><link>https://zhanwei.wang/zh/tags/%E6%B5%8B%E8%AF%95/</link><description>Recent content in 测试 on 王占伟</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Mon, 27 Apr 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://zhanwei.wang/zh/tags/%E6%B5%8B%E8%AF%95/index.xml" rel="self" type="application/rss+xml"/><item><title>「全部测试通过」不等于「需求被满足」——为什么 AI 协作开发常常绿得很可疑</title><link>https://zhanwei.wang/zh/posts/green-but-wrong/</link><pubDate>Mon, 27 Apr 2026 00:00:00 +0800</pubDate><guid>https://zhanwei.wang/zh/posts/green-but-wrong/</guid><description>&lt;p&gt;很多团队把长任务交给 AI 协作执行后，会反复遇到同一种诡异结局：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;任务结束时，CI 一片绿。&lt;/li&gt;
&lt;li&gt;测试报告里展示着几百条新增 spec，覆盖率漂亮，行云流水。&lt;/li&gt;
&lt;li&gt;几天后，产品上线，第一个真用户走完一遍核心流程，触发了一个本该被覆盖却没被覆盖的 bug。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;回头查代码，会发现：那条所谓的&amp;quot;覆盖&amp;quot;测试，其实只是发了个状态码探针；那条所谓的&amp;quot;边界处理&amp;quot;，其实是 &lt;code&gt;console.warn&lt;/code&gt; 加 &lt;code&gt;return&lt;/code&gt;；那个所谓的&amp;quot;功能闭环&amp;quot;，缺了一张数据库表、一个 cookie、一个中间件——但这些缺失都没有让任何测试失败。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;绿色徽章和需求被满足之间，存在一道结构性的缝隙。&lt;/strong&gt; 这条缝隙是 AI 协作开发尤其容易掉进去的陷阱，但它的成因不是 AI 偷懒，而是大多数团队的工程信号根本没有设计来识别它。&lt;/p&gt;
&lt;p&gt;这篇文章想把这条缝隙拆开。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一绿色但错长什么样"&gt;一、「绿色但错」长什么样&lt;/h2&gt;
&lt;p&gt;抛开具体项目，几乎每一例都能归到下面五种形态里：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;软通过测试。&lt;/strong&gt; 测试不是断言契约该有的样子，而是接受一组宽到几乎不可能失败的可能值——&lt;code&gt;expect([200, 400, 403, 404, 409]).toContain(...)&lt;/code&gt;，或者 &lt;code&gt;if (!response.ok()) console.warn('未实现，先跳过')&lt;/code&gt;。这类测试存在的意义只剩下凑数：让&amp;quot;测试数量&amp;quot;指标好看。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;状态码探针冒充端到端测试。&lt;/strong&gt; 名字叫 &lt;code&gt;J-checkout-flow.spec.ts&lt;/code&gt;，里头只发了一个 GET，断言 &lt;code&gt;status !== 405&lt;/code&gt;。&lt;strong&gt;测试名字承诺了一段用户旅程，内容只验证了路由没拼错。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;层级化报告。&lt;/strong&gt; 完工报告写「后端 156 项测试通过，前端 42 项测试通过」。这种描述方式根本无法回答&amp;quot;用户能不能完成 X 操作&amp;quot;这个真问题——你只能从中知道「测试存在，并且通过了」，无从知道它们究竟测了什么。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;藏在源码里的债务。&lt;/strong&gt; 把&amp;quot;未实现&amp;quot;写成代码注释、TODO、warn、文档段落——这些痕迹在 PR 评审里非常容易被忽略，并且永远不会出现在任何 issue 跟踪面板上。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mock 与现实漂移。&lt;/strong&gt; 测试里的 mock 模拟的是接口去年的样子；接口真实形状已经迁移过一次。结果是 mock 在维护一个平行宇宙，测试通过，生产报错。&lt;/p&gt;
&lt;p&gt;这五种状态共有一个特征：&lt;strong&gt;它们都让 CI 显示绿色，但其中任何一种都不能保证用户旅程真的可走。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="二为什么会反复发生不是因为不努力"&gt;二、为什么会反复发生（不是因为不努力）&lt;/h2&gt;
&lt;p&gt;如果你倾向于解释为「AI 偷懒了」「执行者不够尽职」，请先暂停一下。这种解释的问题在于它不可执行——你下次怎么办？让 AI 更努力？让人更细心？长任务下的&amp;quot;努力&amp;quot;和&amp;quot;细心&amp;quot;会在第几个小时之后开始衰减？&lt;/p&gt;
&lt;p&gt;更有用的视角是把它当作信号设计的失败。下面是几个能解释为什么这件事&lt;strong&gt;反复&lt;/strong&gt;发生、而不是偶发的机制：&lt;/p&gt;
&lt;h3 id="机制-1阻力梯度反向"&gt;机制 1：阻力梯度反向&lt;/h3&gt;
&lt;p&gt;写一条严格断言契约的端到端测试：你要先理解需求中预期的具体行为，构造完整流程，让它失败，再去定位修底层 bug。每一步都可能引出更深的修复，可能花几小时。&lt;/p&gt;</description></item></channel></rss>