上一篇我讨论了为什么构建通过不等于任务完成。

继续往下,一个更具体的问题是:类型检查、Lint、单元测试、构建和页面验证,到底该怎样分工?

最省事的回答是“全部都跑”。

但这仍然没有解决三个工程问题:

  1. 某项检查通过以后,我究竟能得出什么结论;

  2. 某项检查失败以后,应该先修实现、修测试,还是先检查环境;

  3. 当时间和环境有限时,哪些验证不能省,哪些可以明确留作未验证项。

我不会把验证手段理解成五道重复的保险,而会把它们看成五种不同的观察窗口。

它们看到的是不同层面的错误,也各自有盲区。

验收先从风险开始,不从命令开始

Codex 修改完成后,我不会立刻机械运行一串固定命令。我会先回到任务和影响范围,列出这次最可能出错的地方。

例如:

改动 主要风险
修改组件 Props 类型兼容、默认值、旧调用方行为
修改表单提交 校验、重复提交、失败恢复、请求数据
修改列表查询 参数转换、页码、请求顺序、空状态
修改局部样式 布局、溢出、遮挡、不同尺寸
修改公共工具函数 输入边界、返回语义、全部调用方
修改构建配置 入口、依赖、资源和目标环境产物

风险列清楚以后,再给每项风险匹配证据。

如果顺序反过来,容易出现一种“检查很多、目标没证”的假繁忙:类型、Lint、构建全部绿色,但真正修改的焦点行为一次都没有验证。

第一类:类型检查负责契约一致性

类型检查最擅长回答:代码中的类型关系是否自洽。

它通常适合发现:

  • Props、Emits 和函数参数不匹配;

  • 返回值与调用方预期不同;

  • 对象缺少必需字段;

  • 可空值未被正确收窄;

  • 枚举、联合类型和泛型使用冲突;

  • 重构后旧符号、旧签名或错误导入仍被引用。

类型检查能够证明什么

在实际命令覆盖的文件和配置中,代码满足当前类型系统表达出的约束。

这句话里有三个限制:实际命令、当前类型系统、已经表达出的约束。

类型检查不能证明什么

  • 类型定义与真实接口响应一致;

  • 业务规则本身正确;

  • 类型断言后的数据真的安全;

  • any、忽略指令或宽泛类型覆盖的位置没有风险;

  • 页面交互、视觉和时序正确;

  • 没有进入当前类型配置的文件也被检查。

下面这段代码可以类型正确,业务顺序仍然错误:

fetchList()
pageNum.value = 1

类型系统知道 fetchList 可调用、pageNum 是数字,却不知道需求要求先回到第一页再请求。

我怎样使用类型检查结果

我会记录:

  • 实际命令;

  • 使用的配置;

  • 覆盖的应用或目录;

  • 是否存在忽略或跳过;

  • 失败是否由本次差异引入。

类型检查失败时,我先判断是契约真的冲突,还是生成文件、路径别名、依赖和环境没有准备好。不能看到红色就让 Codex 随意扩大修改范围。

第二类:Lint 负责静态规则和高频缺陷模式

Lint 更像一套可执行的项目规则。

它可能检查:

  • 未使用变量和导入;

  • 可疑条件、错误的 Promise 使用或不安全写法;

  • 框架相关规则;

  • 导入顺序、命名、复杂度和代码风格;

  • 项目自定义的禁止模式。

具体能检查什么,完全取决于仓库实际配置和插件。

Lint 能够证明什么

被检查代码没有触发当前启用规则中的阻断项,或自动修复后满足这些规则。

Lint 不能证明什么

  • 代码实现了正确需求;

  • 未启用的规则也得到满足;

  • 自动修复没有扩大差异;

  • 页面、接口和状态行为正确;

  • 所有“规范”都已经被配置成机器规则。

我尤其不会把“Lint 无错误”写成“代码质量没有问题”。Lint 只能发现它认识、启用并覆盖到的模式。

自动修复要单独审查差异

如果执行带自动修复的命令,我会在之后重新检查完整差异。

原因很简单:自动修复可能改变导入、格式甚至任务范围外的文件。修复结果合法,不等于差异范围合理。

第三类:单元测试负责可重复的行为断言

单元测试的价值不只是“多一项绿色结果”,而是把关键规则变成可重复执行的断言。

它适合验证:

  • 数据转换和参数映射;

  • 空值、边界值和错误分支;

  • 状态转换;

  • 组件输入输出契约;

  • 指定用户动作后的可观察结果;

  • 已修复问题的回归条件。

单测能够证明什么

在测试提供的输入、替身、环境和断言下,被执行代码产生了预期结果。

测试的证明力度来自断言,不来自用例数量。

一条只断言“组件能够挂载”的测试,不能证明保存失败后输入会保留;十个快照也不一定覆盖请求乱序。

单测不能证明什么

  • 用例没有覆盖的分支正确;

  • 测试替身与真实接口一致;

  • 浏览器布局、焦点和原生行为正确;

  • 测试实现没有复刻同一个错误假设;

  • 公共组件的所有真实调用方式都兼容。

我会先看测试为什么能抓住这次错误

如果新增测试只是让当前实现变绿,却无法说明旧实现为什么会失败,这条测试的回归价值就很有限。

我会让测试至少说明:

  1. 触发条件是什么;

  2. 观察哪个结果;

  3. 哪个错误实现会被它拦住;

  4. 是否覆盖了保持不变的行为。

测试失败时也不能默认实现错了。还要判断需求变了、测试过时、环境异常,还是实现真的偏离了既有行为。

第四类:构建负责集成到产物链

构建位于更综合的一层。它关心代码、依赖、资源和配置能否进入目标产物流程。

它适合发现:

  • 入口或模块解析失败;

  • 构建插件和资源处理问题;

  • 生产配置下的转换错误;

  • 缺失依赖和部分环境变量问题;

  • 产物生成阶段的阻断错误;

  • 脚本中串联的其他检查失败。

构建能够证明什么

当前命令、配置和环境下,目标产物流程成功完成。

构建不能证明什么

  • 用户能够完成目标操作;

  • 接口返回与前端假设一致;

  • 错误、空态、权限和连续操作正确;

  • 页面没有遮挡、溢出和焦点问题;

  • 没有被入口覆盖的代码也正确;

  • 原有调用方行为没有变化。

构建是“能进入交付产物”的证据,不是“产物中的功能已验收”的证据。

第五类:页面验证负责真实用户路径

页面验证把前四类检查没有覆盖的运行环境、真实交互和视觉状态带回来。

它适合验证:

  • 用户能否找到并触发入口;

  • 点击、输入、选择、提交和关闭是否连贯;

  • 请求参数、响应结果和页面状态是否对应;

  • Loading、空态、错误、禁用和恢复是否正确;

  • 弹窗层级、长文本、窄屏和滚动是否可用;

  • 焦点、键盘和连续操作是否符合要求;

  • 直接受影响的原有路径是否保持。

OpenAI 的 Codex QA 用例也强调,执行真实流程前要明确测试环境、关键流程、账号或数据状态,并用复现步骤、期望结果、实际结果和严重程度记录发现。对我来说,这正好说明页面验证不能只写“打开看了一下”。

页面验证能够证明什么

在明确环境、数据、账号状态和操作步骤下,被执行的路径产生了实际观察到的结果。

页面验证不能证明什么

  • 没有走过的路径也正确;

  • 一次手动操作能够替代稳定的回归测试;

  • 所有尺寸、浏览器、角色和数据组合都已覆盖;

  • 代码内部契约和全部调用方都安全;

  • 偶然成功的异步路径没有竞态。

页面验证同样有范围,不能因为“我点过了”就无限扩大结论。

一张五类验证职责矩阵

我会用下面这张表做第一轮分工:

验证手段 最擅长发现 主要盲区 交付时必须记录
类型检查 类型、签名、可空性、契约引用 业务规则、真实数据、运行交互 命令、配置、覆盖范围、结果
Lint 已配置的静态规则和高频模式 未配置规则、业务与页面行为 命令、规则范围、自动修复差异
单元测试 指定输入下的行为和回归断言 未覆盖分支、真实浏览器与接口 用例范围、关键断言、结果
构建 入口、依赖、资源、配置和产物流程 业务、异常、视觉和回归行为 目标环境、脚本定义、结果
页面验证 真实流程、状态、视觉和交互 未执行路径、内部静态契约 环境、数据、步骤、期望与实际

这张表最重要的不是方便打勾,而是防止一项证据替另一项越权。

我怎样安排执行顺序

一般情况下,我会优先获得反馈快、定位直接的证据,再进入成本更高的集成和页面验证。

第 0 步:确认真实入口

先读取项目规则、脚本和测试配置,确认:

  • 使用什么包管理器;

  • 有哪些真实脚本;

  • 类型、Lint、测试和构建分别覆盖哪里;

  • 是否需要生成代码、安装依赖或准备环境变量;

  • 页面运行需要什么账号、数据和服务。

不确认这些内容,后面的命令结果很容易被误读。

第 1 步:运行最靠近改动的静态检查

优先检查目标包、目标应用或相关文件能否通过类型和静态规则。

反馈越靠近差异,越容易快速定位。

如果项目只有全量命令,就使用真实全量命令;如果项目支持可靠的局部检查,也要说明局部范围,不能把它写成全仓结果。

第 2 步:运行能覆盖目标行为的测试

测试选择来自任务风险,而不是文件名相似。

修改参数转换,就找能够断言输入输出的测试;修改组件事件,就覆盖事件时机、负载和旧调用方式;修复异常恢复,就让失败分支真正被触发。

如果没有相关测试,我会记录测试缺口,再根据风险决定补测试还是依靠其他证据,不会虚构“相关测试通过”。

第 3 步:进入目标构建链

前面的直接错误处理以后,再验证代码能否进入项目要求的产物流程。

构建失败时,根据失败阶段回到类型、依赖、资源或配置定位,不要把所有问题都归因于刚修改的业务代码。

第 4 步:按用户路径验证页面

页面验证必须从验收标准生成步骤。

我会至少写清:

环境:本地、测试或其他明确环境
账号与权限:使用哪类角色
数据前置:需要什么记录和状态
操作步骤:按顺序列出
期望结果:页面、状态、请求和提示分别怎样
实际结果:实际观察到什么
剩余问题:失败、阻断或未覆盖项

如果环境不可用,就把这一步标成未执行或无法验证,并说明它阻断了哪条完成结论。

第 5 步:回到完整差异和影响范围

验证过程可能新增测试、更新快照或触发自动修复。最后必须重新审查完整差异,确认:

  • 没有验证过程中产生的临时文件;

  • 没有自动修复造成的无关变化;

  • 所有差异仍能映射到任务目标或验证证据;

  • 受影响调用方的回归范围没有遗漏;

  • 失败和未验证项已经进入交付说明。

验证不是差异审查之后的一条单行命令,而是可能反过来改变差异的过程。

不同任务怎样选择最小证据组合

“最小”不是越少越好,而是刚好覆盖关键风险。

任务类型 通常优先的证据 不能轻易省略
局部类型修正 类型检查、相关测试、差异审查 真实调用方契约
纯数据转换 类型检查、边界单测 真实输入形状或契约依据
列表查询与分页 类型、相关测试、页面路径 请求参数、连续操作和状态恢复
表单提交 类型、测试、页面路径 校验、重复提交、失败恢复
局部样式 构建、页面视觉检查 目标尺寸、长内容和相关状态
公共组件 类型、测试、构建、代表页面回归 旧调用方、默认行为和公开契约
构建配置 目标构建、产物或运行检查 对应环境与入口范围

这张表只能做起点。真实项目已有检查能力、任务影响和失败代价,才决定最终组合。

检查失败后,不要立刻让 Codex“全部修好”

验证失败时,我会先分类。

本次修改引入

失败与当前差异存在明确因果关系,修复范围仍在任务内。回到当前批次修正,再重新运行受影响检查。

历史失败

修改前已经存在,且与当前任务无关。记录基线和对比证据,不把它包装成本次通过,也不要擅自扩展成全仓清理。

环境失败

依赖、服务、账号、数据、网络或配置不满足执行条件。说明缺失条件以及哪些结论因此无法得出。

测试或规则过时

需求和契约已经确认变化,但旧断言或规则仍描述旧行为。先确认新的权威基线,再更新测试,不能为了让实现变绿就直接改期望值。

原因未明

保留失败输出和复现方式,先定位,不把猜测写成结论。

这个分类能阻止一次局部前端需求在验证阶段突然膨胀成“顺手修完整个仓库”。

验证结果不能只有通过和失败

我使用四种状态:

状态 含义
已通过 在明确范围和条件下执行成功
未通过 已执行并观察到与预期不符
未执行 当前没有运行该项检查
无法判断 已尝试,但环境、基线或工具条件不足以形成结论

其中“无法判断”和“未执行”不能写成绿色,也不一定直接否定整个任务。它们要和任务风险一起判断是否阻断交付。

例如局部文案修改没有相关单测,可能不阻断;公共组件契约修改无法运行调用方检查,风险就明显不同。

一份可以直接交给 Codex 的验证模板

# 前端任务验证计划
​
## 1. 任务风险
- 目标行为:
- 主要风险:
- 直接影响:
- 需要回归:
​
## 2. 项目真实检查入口
- 包管理器:
- 类型检查脚本与范围:
- Lint 脚本与范围:
- 测试脚本与范围:
- 构建脚本与目标环境:
- 页面启动与测试条件:
​
## 3. 证据分工
### 类型检查
- 要证明:
- 不能证明:
​
### Lint
- 要证明:
- 不能证明:
​
### 单元测试
- 目标用例与关键断言:
- 未覆盖:
​
### 构建
- 目标应用与配置:
- 不能替代的验证:
​
### 页面验证
- 环境、账号和数据:
- 路径、期望与实际:
​
## 4. 执行结果
对每项使用:已通过 / 未通过 / 未执行 / 无法判断
- 实际命令或操作:
- 覆盖范围:
- 关键结果:
- 失败归类:本次引入 / 历史失败 / 环境失败 / 规则过时 / 原因未明
​
## 5. 完整差异复查
- 自动修复或测试生成的变化:
- 无关差异:
- 回归范围:
​
## 6. 最终结论
- 已有证据:
- 未验证项:
- 剩余风险:
- 结论:可接受 / 修复后复审 / 需要重新规划 / 证据不足

模板中的“不能证明”是我最看重的一栏。

它迫使每个绿色结果留在自己的职责范围内,也让下一项验证为什么存在变得清楚。

写在最后

类型检查、Lint、单测、构建和页面验证不是同一张试卷的五次重复答题。

类型检查守住契约,Lint 执行静态规则,单测固定关键行为,构建检查产物链,页面验证观察真实用户路径。每一种手段都重要,也都不能独自宣布前端任务完成。

我真正需要 Codex 交付的是一份匹配关系:这次改动有哪些风险,每项风险由什么证据覆盖,检查在什么范围和条件下执行,还有哪些事项没有得到证明。

当这份匹配关系清楚以后,验证才不再是“最后把命令跑一遍”,而是前端任务闭环里可以复查、可以解释、也可以承担结论的一部分。

下一篇会进入第 2 周 Day 6:AI 改错以后,到底应该让它继续修,还是清理当前方案重新开始。我会先按目标理解、范围失控、局部实现、契约变化和环境问题给错误分类,再选择纠偏方式。

本系列持续更新。下一步会从“怎样证明改对”转向“发现改错以后怎样止损”,继续完善 Codex 前端任务闭环。

更多推荐