Hotdry.

Article

用 SSE 承载多模型流式补全:断线续传与超时参数

面向多模型流式输出,给出 SSE 连接管理与断线续传的可落地方案与超时阈值清单。

2025-12-11application-security

要让浏览器 UI 测试真正做到「100% 可复现」,业界目前给出的答案不是「再写一条更稳的用例」,而是直接把「非确定性」从根上拔掉。BrowserBook 的思路可以一句话概括:在浏览器内核与自动化脚本之间插入一层「确定性运行时」,录制阶段把随机源、时钟、网络、DOM 种子全部快照化;回放阶段用同一份快照驱动,任何比特级抖动直接报错,实现零方差执行。下面把整套机制拆成 4 个可落地参数,方便你在 Playwright/Cypress 之外快速验证。

1. 确定性时钟:把「时间」变成序列号

参数 录制值 回放值 备注
--deterministic-time-origin 0 0 所有 performance.now () 起点对齐
--advance-time-step 16ms 16ms 每帧固定步进,与屏幕刷新解耦
--request-animation-rate 禁止浏览器抽帧,确保动画帧对齐

实现方式:在启动浏览器时注入 Date.now = () => timeOrigin + frameCount * 16,并把 requestAnimationFrame 重写成「计数器 + 1」。这样即使 CI 机器性能不同,同一用例的动画、轮询、超时都会落在同一毫秒刻度。

2. 网络快照:把「异步」变成「常量数组」

参数 录制值 回放值 备注
--record-network true false 录制阶段拦截所有 fetch/XHR
--replay-network false true 回放阶段用录制 JSON 直接返回
--network-delay-jitter 0 ms 0 ms 强制延迟为 0,消灭 RTT 方差

实现方式:基于 Playwright 的 route.fulfill(),把第一次运行的全部请求按顺序写入 network.dump.json,内容包括 URL、status、headers、body、时间戳。回放阶段不再发真实请求,而是按时间戳顺序直接 fulfill,彻底消灭 404、慢查询、A/B 分支带来的抖动。

3. 随机种子:把「Math.random」变成「伪随机表」

参数 录制值 回放值 备注
--seed-random 42 42 全局 Math.random 替换为 seedrandom
--seed-crypto 42 42 把 crypto.getRandomValues 也劫持
--uuid-version v4→v1 v1 用时间戳 + 计数器生成 UUID,避免随机

实现方式:在页面脚本最前端注入 window.Math.random = new seedrandom('42'),并代理 crypto.getRandomValues 返回「录制阶段预生成」的随机数表。只要种子相同,React key、弹窗位置、颜色随机化都会完全一致。

4. DOM 快照与重放:把「可见状态」变成「可执行脚本」

参数 录制值 回放值 备注
--snapshot-format json+base64 json+base64 包含 outerHTML、样式、input value
--snapshot-interval every action every action 每次 click/type 后自动快照
--replay-strategy strict strict DOM 哈希不一致立即抛错

实现方式:

  1. 每步操作后执行 document.doctype + document.documentElement.outerHTML,并把 <input><textarea><select> 的当前值写回 DOM,生成「自包含快照」。
  2. 快照文件按序号命名:001-login.json002-search.json……
  3. 回放阶段用 page.setContent() 直接覆写整个文档,再执行下一步操作;若哈希与录制不一致,立即截图 diff 并抛错,实现「时间旅行」级别的现场还原。

5. 断线续传:让 CI 机器也能「接着跑」

即使所有状态都被快照化,CI 容器被强制重启仍会导致用例从头跑。BrowserBook 在 SSE 通道里加了两条指令:

指令 客户端行为 服务端行为
snapshot/restore?case=login&step=7 断线重连时先拉取第 7 步快照 返回对应 JSON 并回滚浏览器状态
snapshot/diff?case=login&step=7 校验本地快照是否一致 返回 204 或 412,412 时强制重跑

实现方式:

  • 用例脚本在每一步操作后把「用例名 + 步骤号」通过 SSE 发送到服务端;
  • 服务端把快照存到 Redis,TTL 24h;
  • 客户端断线重连时带 Last-Event-ID,服务端按 ID 恢复上下文,实现「秒级续跑」。

6. 超时参数清单:不给「随机延迟」任何机会

阶段 推荐值 说明
页面加载 5 s 网络已快照,超时即视为快照损坏
元素可见 2 s 回放阶段禁用智能等待,超时直接抛错
动画结束 1 s RAF 已固定帧率,1s 足够跑完 60 帧
网络空闲 0 ms 回放阶段无真实网络,可设为 0
重试次数 0 确定性运行不需要重试,失败即缺陷

把以上 6 组参数写进 browserbook.config.js,你就能在本地开发机、CI 容器、甚至多模型并发跑的场景下,得到「像素级」一致的测试结果。下一步要验证的,不再是「这条用例稳不稳」,而是「快照有没有覆盖新功能」—— 这才是 UI 自动化真正的确定性未来。


资料来源
[1] Playwright 官方文档:Trace Viewer 与 UI Mode 时间旅行调试机制
[2] Mozilla WebReplay 项目:记录与回放 JavaScript 行为、DOM 结构及图形更新

application-security