工程化、测试与性能 · KNOWLEDGE CHAPTER
K24

自动化测试

测试是一组有边界的证据,而不是“通过”标签。先定义用户需要完成的任务,再挑能暴露该风险的最低成本层级;时间、网络和身份等不确定输入可控,系统真正需要协作的部分则要保留。

工程化、测试与性能2 道章节练习7 道主练关联

核心模型

测试是一组有边界的证据,而不是“通过”标签。先定义用户需要完成的任务,再挑能暴露该风险的最低成本层级;时间、网络和身份等不确定输入可控,系统真正需要协作的部分则要保留。

原理与机制

按风险选择层级

纯校验、排序和数据转换适合单元测试,组件测试保留事件、状态与视图的协作,少量端到端测试贯穿浏览器、路由和后端。层级越高,能暴露的集成失败越多,但数据准备、运行时间和故障归因也更贵。表单提交的“接口成功”和“到达正确详情页”是两项结果;只断言 navigate 被调用,无法发现目标分块 404。测试数量不应机械按金字塔比例分配,而应围绕重复创建、权限失败和恢复路径。

在真实边界替换不可控因素

把 fetch 所在模块全部替换,可能连序列化、错误映射和请求地址也跳过。网络层模拟能让生产请求代码继续执行,但模拟数据仍可能与后端一起过时,因此要配合独立契约证据和少量真实环境流程。schema 可以检查字段形状,却未必发现“空页仍有下一游标”的语义变化。夹具要覆盖缺字段、慢响应、空值、过期身份、重复游标,未匹配请求应明确失败,各用例隔离共享状态和 handler。

控制时间,也控制谁被推进

300ms 防抖应在 299ms 与 300ms 两侧断言,而不是 sleep 猜机器速度。定时器回调会创建 Promise 续体时,需要异步推进时钟并等待组件刷新;推进假时间不代表真实网络也已完成。卸载后先验证业务确实取消任务,再恢复真实时钟,不能清空残留来掩盖泄漏。clear、reset、restore mock 分别针对记录、实现或原方法,不能互相代替。日期测试还要固定时区与语言,分清 UTC 时刻、当地日期和单调经过时间,并覆盖跨午夜、月末与夏令时。

让等待表达业务条件

Playwright 的角色和可访问名称定位更贴近用户,但定位成功也需处理歧义。自动可操作性等待能判断点击条件,不能保证保存已成功;结果应使用可重试的界面断言。必须等待某响应时先注册等待再触发,随后仍检查页面,防止 HTTP 200 显示旧数据。CI 偶发失败先看 trace、网络和截图,区分遮挡、慢服务与数据争用;force、固定延时和不断增加重试只能隐藏症状。

覆盖界面生命中最脆弱的阶段

流式 SSR 的 shell、后续片段和客户端水合是三个观察点。分别在 shell 前后注入错误,检查状态码、局部边界、console 与真实交互;响应头已发出后不能改成 500。自动无障碍扫描也只覆盖部分规则,需在弹窗、错误提示等动态状态测试键盘和焦点,再用目标读屏工具检查任务是否可理解。测试报告要说明覆盖设备、状态和盲区,零告警不是全面达标。

最小示例

javascript
javascript
// 已导入被测 debounce;使用 Vitest
vi.useFakeTimers();
try {
  const send = vi.fn();
  const search = debounce(send, 300);
  search('a');
  search('ab');
  await vi.advanceTimersByTimeAsync(299);
  expect(send).not.toHaveBeenCalled();
  await vi.advanceTimersByTimeAsync(1);
  expect(send).toHaveBeenCalledTimes(1);
  expect(send).toHaveBeenLastCalledWith('ab');
  search('abc');
  search.cancel();
  await vi.advanceTimersByTimeAsync(300);
  expect(send).toHaveBeenCalledTimes(1);
} finally {
  vi.useRealTimers();
}

前两个断言给出触发边界,第三组证明取消契约,避免只看最后调用次数而漏掉过早请求。若被测对象是组件,还需卸载并等待其更新;这里的函数级示例并不证明浏览器中文输入或真实网络兼容。

核验:Node v24.19.0:ESM语法检查通过;Vitest与生产debounce为项目依赖,本例未执行Vitest行为测试。

边界与取舍

边界

  • 网络 mock 与 schema 来源于同一个错误假设时,两者同时变绿不构成独立验证。
  • 冻结 Date.now 不会自动冻结所有定时器;假时钟不能把尚未到达的网络响应变出来。
  • SSR HTML 有正确文字、axe 零告警,都不能证明水合后键盘流程可用。

取舍

  • 更真实的测试提升边界可信度,也增加夹具、权限和隔离成本;把高风险路径留在真实集成层。
  • 重试降低偶发环境噪声,但会延长反馈并掩盖竞争;保留首次失败证据并统计 flaky 比例。

口述示范

我先列用户结果和失败边界,再分配单元、组件、契约与端到端覆盖。时间和数据可控,断言看业务可见结果;SSR、无障碍和跨时区则补足自动工具看不到的阶段。

章节练习

练习 1

保存已创建记录,但目标页面加载失败,应在哪层发现,恢复时重做什么?

展开检查点
  • 保留真实路由的集成或端到端用例。
  • 断言只创建一次;恢复导航已有记录而非重新提交。
练习 2

为慢评论 SSR 页面写测试矩阵,同时覆盖键盘操作和促销截止时间。

展开检查点
  • 区分 shell 前后错误和实际状态码,检查水合交互。
  • 冻结时钟及指定时区,补目标读屏人工验收;服务端裁决截止时间。

参考来源与核验边界

2026-10-04 核验。Vitest mock 清理与异步计时 API、Playwright 时钟覆盖范围按锁定版本复核;示例为测试骨架,需项目导入与配置。

内容版本:2026-10-04.2 · 题目和来源 ID 保持原样,本站不将面经标签解释为企业官方出题或高频保证。