tv-test

GitHub

Bili WebOS TV测试验证方法论,涵盖发版前五层自动管线、真机CDP测试、旧设备兼容及严格验证纪律。

.claude/skills/tv-test/SKILL.md asdf17128/bili-webos

Trigger Scenarios

修改service或app代码 修复Bug后验证 版本发布前检查

Install

npx skills add asdf17128/bili-webos --skill tv-test -g -y
More Options

Non-standard path

npx skills add https://github.com/asdf17128/bili-webos/tree/main/.claude/skills/tv-test -g -y

Use without installing

npx skills use asdf17128/bili-webos@tv-test

指定 Agent (Claude Code)

npx skills add asdf17128/bili-webos --skill tv-test -a claude-code -g -y

安装 repo 全部 skill

npx skills add asdf17128/bili-webos --all -g -y

预览 repo 内 skill

npx skills add asdf17128/bili-webos --list

SKILL.md

Frontmatter
{
    "name": "tv-test",
    "description": "bili_webos 的测试与验证方法论 — 发版前验证管线、真机 CDP 测试、旧设备(webOS 5\/Node 8)兼容、修 bug 的验证纪律。改动 service\/ 或 app\/、修 bug、发版前都应使用。"
}

bili_webos 测试与验证

一键管线(发版前必跑)

bash tools/verify.sh          # 全链路:语法 → 真Node0.12/8 → 构建 → 部署 → 真机DOM检查
bash tools/verify.sh --no-tv  # 只跑本地层(电视不在时)
bash tools/verify.sh --full   # 额外跑真机 UI smoke(test-ui.mjs,~3分钟)

五层,逐层 fail-fast:

  1. syntax — service 全部文件用 acorn 按 ES5 解析(webOS 4.x = Node 0.12.2)
  2. node8 — docker x86 内分别运行真实 Node 0.12.2 和 8,跑真实 service.js:stub webos-service、驱动 fetch handler 真连 api.bilibili.com、调 getDiagnostics。见 tools/test-node8/
  3. build — vite 生产构建
  4. deploy — build.sh 部署 + tools/launch.mjs 重启 app
  5. device — CDP 断言:卡片>5、侧栏存在、0 张裂图,并存截图

验证纪律(血泪教训,违反必翻车)

  1. 正对照原则:先证明测试方法能复现 bug,再声称修复已验证。 做法:git checkout <旧commit> -- <文件> → 部署坏版 → 同一操作复现 bug → 恢复新版 → 同一操作确认消失。边缘滚动 bug 连续两个版本"修好了"都是假的,就是因为没做正对照。
  2. 失败路径必须测。 诊断页/错误处理类功能,happy path 全绿毫无意义 —— 用 Playwright route.abort() 掐断 API,确认错误文本上屏、进报告。
  3. 测试结果反常时,先验证测试工具本身。 在页面挂原生事件计数器(document.addEventListener('mousemove',...,true))再注入 CDP 事件 —— 曾经 CDP 鼠标注入静默失效,把"工具坏了"误判成"产品坏了"浪费了一整轮。
  4. 交互语义用受信输入管线验证:npm run dev + Playwright(page.mouse/page.keyboard 走真实 Chromium 输入管线),addInitScript 干掉 window.webOS 强制走 proxy,page.route mock 数据流(mock 端点注意 wbi 路径:**/top/feed/rcmd**)。TV 的 CDP Input.dispatchMouseEvent 不可靠,不要依赖它测 hover。

旧设备(webOS 5/6)兼容

  • service 层 = Node 8:没有 URL/URLSearchParams/globalThis 全局、没有 ?./??/optional catch binding。new URL 要写 require('url').URL(曾导致 webOS 5 全部请求失败,#10/#13)。ws 必须 v7(v8 要 Node 14)。
  • app 层 = Chromium 68(webOS 5)/ 79(webOS 6):vite legacy 插件管语法;要防的是缺失的全局(globalThis 已 polyfill)和新 Web API。
  • 官方模拟器:VirtualBox Emulator 只到 webOS 6.0 且 x86-only(Apple Silicon 跑不了);Simulator 只覆盖 webOS 22+。→ 所以用 docker node:8 测 service,这是最接近真机的手段。
  • 新增 service 依赖/语法时:npx acorn --ecma5 --silent <file> 快速把关,再跑实际运行时。

真机工具箱(tools/)

工具 用途 坑
launch.mjs <appId> 启动/切换 app 必须 luna-send-pub(公共总线);私有 luna-send 对 prisoner 永远 Permission denied
wake.mjs WoL 唤醒电视 (MAC 14:7f:67:a1:6b:56)
drive.mjs "keys" 遥控按键 + STATE 从未知焦点开始导航不可靠,先 left,left 回侧栏
point.mjs "move:x:y,wheel:d,click" 指针模拟 + focus/underPointer/match 注入可能静默失效(见纪律3);端口已改 ephemeral
eval.mjs "<expr>" 页内执行 JS 验证 UI 状态首选(截图对 GPU 层是白的)
screenshot.mjs 真机截图 视频/GPU合成层截不到
test-ui.mjs 真机 UI smoke 全家桶 app 须在前台
test-e2e.mjs API 集成测试 需先 node proxy/server.js

深链直达(测试专用钩子,owner 授权 2026-07-10)

"没法测试 = 不允许上线"。为可测试性可以给 app 加专门的测试钩子。

  • window.__openVideo({bvid, cid, title})(App.jsx 注册)——CDP 里直接播放指定视频, 跳过整个 UI 导航;入口与卡片按键完全同路(normalizePlay 起全是生产代码)。 找"具备某特征"的测试素材(有字幕轨/有章节/多P):先用页内 luna fetch 查 history/cursor 或 player/v2,拿到 bvid+cid 再深链。
  • 保持瞬态 UI 存活以便截图(scrub 气泡这类 1s 自动消失的):页内起 setInterval(()=>dispatchEvent(new KeyboardEvent('keydown',{key:'ArrowRight'})),700) 合成键反复续命,另一个连接从容截图,完事 clearInterval。合成键走 JS 层 keydown handler,足够(不需要 trusted input 时)。
  • 逐卡片盲探(back,right,ok 循环 + eval 断言)是没有素材线索时的兜底,慢但可靠。

专项验证清单

  • QR 码功能:报告体必须纯 ASCII(CJK percent-encode 后 1 字变 9 字,QR 密到扫不出);用 jsQR 从真机截图解码验证,再开解码出的 URL 确认 GitHub 表单预填(body 在第 3 个 textarea,前两个是 GitHub 反馈组件)。
  • 诊断页:真机 happy path 全绿 + dev 掐断 API 全红,两头都要。
  • 悬浮 UI(气泡/弹层):getBoundingClientRect 只给布局位置,测不出 overflow 裁剪 —— 必须截图看像素。.player-controls 是 overflow-y:auto,往上探出的元素会被静默裁掉(v1.2.4 预览气泡被裁就是这么漏掉的);悬浮层挂到根节点。
  • 播放器改动:ended 决策逻辑(收藏连播 vs 分P)可用真实数据在本地 node 里跑决策函数做确定性验证,比 flaky 的真机播放可靠。

Case 沉淀(硬性规则)

开发完成 → 验证过的场景必须追加到 docs/TESTCASES.md(带事实佐证:抓过的真 bug 或正对照记录); 发布前按 docs/DEVELOPMENT.md 的门禁清单回归。能自动化的 case 升级进 tools/verify.sh。

丰富本 skill

每次踩到新坑/建立新方法,追加到对应小节。宁可啰嗦,不可失传。

通用方法论的正式版在独立仓库 ~/code1/webos-tv-skill(github.com/asdf17128/webos-tv-app-skill,reference/testing.md)—— 本文件放 bili_webos 项目专属细节(IP/密钥/工具名),提炼出的通用经验要同步一份过去。

2026-10-06:4.x 与播放卡顿

  • Node 0.12.2 的 URL/Buffer/String/CA 与旧 ws 兼容由 service/compat.js 提供,必须最先加载;语法门禁降为 ES5,真实运行时门禁同时测 0.12.2 和 8。Docker 历史镜像可能拉不下来,使用官方 SHA256 校验二进制;Apple Silicon 旧 CLI 参数异常可经 ELF loader 启动,记录实际 process.version。
  • 模拟播放停滞时,Playwright clock 必须在播放器创建计时器前安装。readyState=1 是缓冲耗尽,不能把它排除出卡顿检测。暂停/seek/退出必须不会继续重试。
  • 设置页添加新开关后,要同步遥控器回归的行顺序。2026-10-06 全量回归发现 #27 新开关使旧测试点错行,更新顺序后浏览器与真机均复验。
  • 诊断二维码必须按整数像素绘制并保留 quiet zone,重复错误去重;变更后,tools/test-cdn-tv.mjs 从真实电视截图用 jsQR 解码,核对选路和最近播放节点;测试结束恢复所有偏好与坏 CDN 注入标记。

2026-10-06:模拟与真机广覆盖补验

  • 构建成功与 DOM 数量正确不证明画面正确。本次评论栏缺少 JSX 花括号,条件源码与空态直接显示在已加载评论旁;截图才发现。新增改前失败的复现,同时断言条件文本、空态互斥和控制条几何,并看模拟/真机截图。
  • 真实评论接口返回数量会变化;对照同一次 API 响应,不用固定的“至少 5 条”。异步焦点恢复使用有上限的状态等待,不能用任意 100ms 睡眠判失败。
  • 账号是否有效以 /x/web-interface/nav 为准,残留 SESSDATA 不证明已登录。账号增删测试默认跳过;SIM_ACCOUNT_WRITES=1 仅限独立测试账号。TV_ACCOUNT_WRITES=1 已改为固定测试视频、完整原列表快照、请求层精确 aid 保护与 finally 清理,用户已授权账号测试时可启用。跳过不计为通过。
  • 保留首次失败、修复后结果和真机失败响应。本次 UP 投稿真机返回 -352,即使 Mac 同接口成功也不能冲抵;记录环境并保留待验收状态。采集响应码/条数即可,不把签名 URL 或认证信息写入证据。
  • 动态标签页不能靠固定按键次数证明命中。有“选集/合集”时初始标签不同,旧测试会把相关推荐当作 UP 投稿通过;必须同时核对选中标签和该标签 API 的成功响应。
  • 稍后再看测试不能按标题片段决定删除对象。采用原列表不存在的固定视频,长按后核对 card-menu 事件的 aid;请求层只允许该 aid 的单条 add/del,结束比对原列表顺序与成员。账号截图只留本地。
  • 安静直播间短时间没有弹幕,不能直接判中继坏了,也不能只凭图层存在判通过。testLiveRelay 动态选当前在播房间,分开记录 token 响应码、Luna 订阅、实时帧数与 DOM 数量,并截实际弹幕;历史聊天不算实时帧。

2026-10-06:原生 HLS 起播测量

  • LG C4 原生视频暴露 requestVideoFrameCallback 却未回调;分别记录 API、playing、元数据后 currentTime 实际推进、解码尺寸,不能把时间推进写成逐帧画面测量。tools/probe-live-startup.js 的 default 模式测生产选源,其他模式仅筛选真实响应的格式;不要保存带签名的流 URL。
  • 比较 TS/fMP4 时保持 qn、编码与解码尺寸相同,记录 CDN 主机差异,交替采样并区分冷/热启动。首次 TS 慢不代表热启动每次都慢;先用真实数据定位瓶颈,最终无覆盖测部署版本,并继续观察起播后的 waiting、error、重连。
  • 播放 URL 和画质阶梯必须来自同一次选定格式响应,避免默认画质请求覆盖正在播放的元数据。加载提示等实际 playing 才消失;用受控事件覆盖格式回退、超时最终错误、手动重试、完整解码阶梯和退出后迟到响应,再看加载/失败截图。
  • 真机画质按钮显示当前画质(如“原画”),不是固定“画质”。用 TV_LIVE_ROOM 选当前有多档的房间,切换及切回都等实际播放事件;仅有一档时明确跳过切换,不能判产品失败,也不能假称已验证。

2026-10-06:自动 CDN 验证

  • 节点名含“海外”不证明在当前网络快。测真实媒体 Range,核对 206、起止范围、总长度与完整响应体;超时部分下载可供诊断,但不能作为自动选路成功。两次采样取较慢值,切换留门槛,避免一次缓存命中决定长期选择。
  • 自动测速必须等暂停/缓冲充足;换源、低缓冲和退出取消不应污染健康缓存。缓存只含主机与测量信息,不能存签名 URL。候选必须能被缓存:本轮正对照发现 .bilivideo.cn 不能缓存时会反复占据队列,旧逻辑 10 次 tick 发 20 个请求,修复后仅 2 个且其他节点继续得到机会。
  • 设置值和 MPD 顺序不证明实际选路。浏览器测试经生产请求过滤器检查发出的请求,标清 Shaka/解码替身;真机另查 Shaka 的实际媒体响应,seek 到已缓冲区之外并验证进度继续、播放器实例不变。测试后恢复原偏好、测速缓存和故障注入标记。
  • CDN 设置截图只截弹窗,避免把账号页发布到公共仓库。Akamai 原生签名、仅 Akamai 源和直播 URL 都要作为禁止通用 host 改写的回归场景;本地网络测试不等于海外验收。

2026-10-06:快速重试与实际焦点

  • 重试请求可能在 React 提交 loading=true 前完成,true/false 被批处理合并。先在输入事件中提交加载态,再开始副作用请求;测试必须包含立即完成的 Promise,只有网络延迟用例会漏掉。

  • 白框不等于焦点系统可用:真机复现了旧按钮的 passive cleanup 在新卡片已高亮后清掉全局焦点,下一次方向键跑回侧栏。注册/注销改为 useLayoutEffect,与 DOM 同次提交;__focusState() 核对真实目标,再按方向键、断言只有一个高亮。保留“只修加载态仍失败”的中间证据。

  • -352 不能一律归咎账号或网络。排行榜本轮只改 Referer,就从两次 -352 变为两次 code=0/100 条;修生产服务和独立代理共享策略,并通过真实 Node 0.12/8、C4 六分区验证。不要把游戏失败改成跳过来让测试全绿。

  • 海外探针必须匹配生产错误语义:本轮初版 worker 把 API HTTP 412 抛成异常,提前中止,漏测 app 已有的 pagelist 回退。纠正工具后 HK/JP 均能取流并实收分片。服务器线路、模拟媒体事件与电视实际解码分开陈述,匿名探针不上传用户 Cookie 或保存签名 URL。

  • 注册生命周期必须覆盖手动注册者:SearchPage 原生输入框绕过 useFocusable,仍用 passive effect 清理,导致切到设置页时删掉刚注册的第一行。新增搜索 → 设置 → 下 → 上正对照(改前 0/1、改后 1/1),手动注册也改为 layout effect;不要通过把测试起点改到第二行来掩盖真正回归。

2026-10-06:发布前核对社区补丁边界

  • 部分移植必须读上游 PR 的完整说明:PR #17 明确指出单独开启 4K120 的杜比信令会引入黑屏风险。未移植专用帧转换时,超过 60fps 或帧率未知保持原有基础层信令;MSE 接受 codec 字符串不证明该帧率可解码。用真实 PlayerPage 生成的 MPD 证明旧实现 0/2、新实现 2/2,再覆盖正常帧率的 DV 和音轨回退。

2026-10-06:片尾模式与设置迁移

  • 片尾测试必须经过真实 PlayerPage 的 ended handler:只测辅助决策函数会漏掉收藏、稍后再看、分 P、合集和分页入口绕过全局偏好。正对照 v2.2.0 在这五种入口均加载下一条,普通推荐视频停止;电视另用真实媒体自然触发 ended,不能把人工 dispatch 当成解码验证。
  • Playwright addInitScript 会在每次 reload 重跑;验证持久化时只在没有存储值时初始化设置。无条件重种默认值会把测试工具清空设置误判为产品丢失偏好。
  • 真机测试开始前用公共 Luna launch 保证应用在前台。已退出应用留下的 CDP 页面可能仍可读 DOM/storage,但 reload 后不会恢复 React 测试入口;保留这类准备阶段失败,重新前台启动后再做同场景对照。

2026-10-06:起播与弹幕性能对照

  • Shaka load() 返回不等于媒体已到 loadeddata;真机旧版在出画面之前就解析弹幕/加载推荐。采样从打开入口监听原生事件,辅助请求用真实媒体就绪门控,并测退出后的迟到事件。性能监听也应在加载前注册,否则漏掉早到事件。
  • 优化并行请求必须保持续播语义:同 cid 去重,跨 cid 重新取正确的流/章节/字幕;失败结果不能当成功缓存。低网速模拟用可控延迟检查请求先后,不能只看总耗时一次变快。
  • 弹幕测试同时量化长列表访问量和动画节点峰值。只限制节点不解决全列表扫描;只改算法不约束合成层数量。浏览器 6 倍 CPU 限速不是旧电视仿真,rAF 也不是视频解码帧率;保存旧版失败与真机对照,恢复设置/响应拦截器。
  • 故障 CDN 测试不要固定睡 12s 后直接 seek:重试尚未结束时,Shaka load 的起点会覆盖测试 seek,出现“已播放且已拉黑但 t=3s”的假阴。独立 fixture 从头播放,等原生进度后再 seek,并有界断言 seek 后继续前进;不可通过放宽进度阈值隐藏问题。

2026-10-06:控制栏压缩与起播阶段诊断

  • 高推荐列表放进限高的纵向 flex 容器,会把 6px 进度条压成 0px。正对照需包含真实按钮数量、多行推荐、长标题和大字号,同时检查进度条高度、各行边界与返回按钮后的可见焦点。垂直内容可用普通流与显式 margin,避免旧引擎的 flex 压缩和 gap 缺失;强制旧 CSS 的现代浏览器测试仍不是 Chromium 53 整机验证。
  • 起播阶段从请求发出时计时,不能等并发任务被 await 时才起表;并行时长不可相加。Shaka load、首个分片响应、loadedmetadata、loadeddata、playing 分开记录,loadeddata 不是逐帧上屏测量。未知值用缺失标记;取消/失败保留部分数据,退出后的迟到任务不能覆盖下一条视频。
  • Vite HMR 给模块 URL 添加时间戳。测试直接 import 无时间戳路径会得到另一份模块内存,误把真实播放报告读成 null;读取实际已加载的 resource URL 或从产品 UI 观察,不能以重复模块的空状态判产品失败。

2026-10-07:Blob DASH 的隐式 MIME 探测

  • 真实 Shaka 4.16.24 对无扩展名 Blob 的 load(url) 会 HEAD 探测 MIME;Chromium Blob HEAD 返回 HTTP_ERROR,4 次失败后改 GET。Blob 自带 type 不等于播放器知道格式,生成 DASH 时给 load 第三个参数 application/dash+xml,并覆盖画质回滚入口。
  • tools/test-manifest-mime.mjs 用真实网络栈、相同空 MPD 的同一终止解析错误作正对照,仅证明多余探测;不能将测试耗时当电视出画面提速。Shaka retry 事件包含清单与媒体,错误 data 布局按 code 不同;报告需分类,不能把全部次数标为媒体/CDN失败。
  • 第一条媒体响应可能是 SegmentBase 索引;公共 segmentappended 才表示媒体写入完成,但仍不等于画面上屏。记录首个节点,不能用后台测速后的最后节点推断起播选路。

2026-10-11:恢复与关注测试

  • 本机回环就绪探针须绕过代理并要求 HTTP 成功。curl -s 收到代理 502 仍退出 0,会把未启动服务当成正常;使用 --noproxy '*' -f,不要把连锁失败当产品回归。
  • 恢复测试要保留原 cid/位置,覆盖 DNS 恢复但没有 online 事件、长期断网预算耗尽和退出取消。只把加载改成重试按钮不足以证明恢复。
  • 真机合成 mouseenter 不保证触发 React onMouseEnter;本次测试已改用 CDP 遥控方向键逐项选择,并验证实际 focused 控件再按 OK。
  • 关注等写入须明确区分隔离 API 成功路径、真实关系读取和真机拒绝路径。菜单关闭后服务器才确认成功,仍应更新同账号的全局缓存;不能向已切换账号的缓存回写。

2026-10-11:请求总超时与快进时序

  • Node ClientRequest.setTimeout 依赖已分配 socket;真实 http.request 的未完成 lookup 与满 Agent 队列需要独立的响应头总期限。正对照让 lookup 不完成,旧 socket timeout 不触发;新期限保证恰好一次错误回调并销毁请求。收到 headers 后清除总期限,保留流的空闲超时;正常完成后的 close 不能再销毁已归还连接池的请求 socket。真实 Node 0.12/8 都要测排队路径。

  • 快进取消必须记录电视上的 keydown 到达时间及原生 seeking 事件。即便同一 CDP 会话,按键之间的任意状态查询/固定等待也可能超过 1s 自动提交窗口;减少控制回合,在输入之后读完整记录。分别覆盖 <1s Back 取消、OK 立即提交和 >1s Back 前已自动提交,不能用更宽的进度容差隐藏误提交。此前无时序记录的失败不能事后断言原因已证明。

  • 长时间网络验证将连续实际播放与定时 API 读取分开记录,并检查服务 uptime 单调增加,防止后台重启掩盖故障。单次 25 分钟成功不等于复现并修复所有 DNS/路由器故障。

  • 长播中的单个 socket hang up 不能归类为全网断线:同步记录主站、直播、更新源、实际解码和 service uptime。读取请求仅在 headers 前的连接重置/EPIPE 允许一次新连接重试,沿用原总期限;必须覆盖 POST 不重发、部分响应不重发、取消重试和旧 Node 运行时。保留抓到真实失败的耐久记录,改后重新完整计时,不能跳过失败样本。

2026-10-13:退出会话与服务端口协商

  • 退出登录要同时覆盖 UI、前端存储、后台内存和持久化文件;前后端各自隔离退出前的异步响应。至少测试上游迟到 Set-Cookie、已生成但未交付的响应、持久化失败、超时和重复确认。不能只断言用户名消失;失败不能显示成功。匿名风控指纹与账号凭据分开处理。
  • 老浏览器兼容测试要模拟“接口存在但成员缺失”,不止删除整个全局对象。IntersectionObserver 可用不意味着 isIntersecting 可用;保留真实几何与滚动,仅删除成员来做正对照。
  • 动态避让端口必须经过真实端口占用测试,等服务实际 listening 后再协商地址,核对封面解码和 Range 响应。现代 Node 的 server.listening 属性不能用于未验证的旧 Node;用 listening/close 事件状态并在真实旧运行时验证。
  • Playwright clock 会替换 performance;需要通过资源 URL 找到 Vite 实际模块时,在安装时钟前缓存引用。图片 naturalWidth>0 只证明解码,截图应等图片加载类及淡入完成。
  • 本地真实服务验证使用隔离 Cookie/配置目录;仅在文件系统与上游边界替换依赖,保留生产 handler 和真实 HTTP socket。模拟 API/媒体字节不等于硬件解码,不应据此关闭未复现的 CDN 403 报告。

2026-10-13:真机新文档注入与退出验证

  • 在电视 CDP 使用 Page.addScriptToEvaluateOnNewDocument 前先 Page.enable,并在注入代码内写可读标记。这轮未开启 Page 域时脚本返回 identifier,但刷新后的注入标记不存在、目标 API 仍在;开启后同一删除属性与图片解码断言通过。不能只凭注册成功就认为故障条件已生效。
  • Page.reload 应答可能早于新文档;旧 DOM 已满足 ready 条件时会产生假结果。先在旧 window 写唯一标记,再等标记消失和新文档 ready,然后等待真实图片/内容。
  • 真实退出测试先在内存和权限 0600 的私有备份中保留恢复所需状态,finally 恢复并向服务端核对相同账号,成功后删除备份。公开报告只写布尔状态/响应码/哈希,用户历史、Cookie 和账号截图留在本地。
  • 动态端口可通过设备回环转发器和 Luna 元数据注入验证真实媒体请求及解码;明确它与生产服务端口占用回退的测试边界。结束移除新文档脚本、重载并关闭转发器。

2026-10-13:会员与高分辨率硬件验证

  • ignoreHardwareResolution 解决 3996/4096 宽影院源被面板宽度误拒,但不能无条件放开 8K。C4 真机 MSE 接受 8K、Shaka load 成功、readyState=4,却 currentTime 长期为 0;必须保留设备分辨率边界,另测 8K→4K HDR 与影院宽度同时成立。
  • 跨编码不能以更大 bitrate 作为“更好”:同档 HEVC 优先可显著减少 4K 传输,仍需实际 codec 失败→同档 AVC 测试。Profile 5 不可伪装为普通 HEVC 基础层。
  • PR #17 转换需校验全部 35 个分片及末尾短片;真实完整播放还要自然 ended、时间轴、解码帧数。runtime.fragments 统计响应次数,会含重复下载,不能要求它恰好等于 35。保留首次计数断言失败与数据,再修正工具,不能悄悄改成通过。
  • 安装工具早期状态事件不代表完成;重开前台并确认可见、钩子就绪、安装 bundle 哈希。遥控切画质先判断当前焦点,不能无条件 ArrowUp;等待媒体 readyState≥2,不能在 loadedmetadata 就判恢复。
  • 会员测试必须查 nav 的 vipStatus,再测带“会员”badge 的 PGC 集数。可读集数/取流成功、真实解码推进、面板 DV 标志、Atmos 音响输出是不同证据层级。

2026-10-13:暂停后的致命错误与原生签名备地址

  • MEDIA_ERR / Shaka 致命错误可能把 video.paused 置为 true。只靠“播放中无进度”的 watchdog 会漏掉,必须独立覆盖运行期错误与原生倍速源错误。加载期错误应继续交给编码/音轨回退,不可提前弹出通用失败;重复事件不能重复重建,退出清理与重试预算都要测。
  • 原生主/备 CDN 地址即使 host 相同,也可能有不同 path/query。手动选线、格式探针、诊断和测速应保留完整原地址,成功后复用它;不要先丢掉 URL 再用 host 重建。所有请求失败仍必须显示失败,不能只测 happy path。
  • TV 错误注入证明的是恢复机制,不等于复现了报告者的网络/解码根因。截图只证明 UI,实际进度、解码尺寸和编码另行检查。旧版没有的 CSS 类不能作为旧包失败状态探针。
  • 不要在 Vite 浏览器套件进行中修改应用源文件;HMR 会改变播放器生命周期,污染续播/请求次数断言。使用虚拟时钟时也不能假设 Resource Timing 一定保留了早期模块条目。

2026-10-13:区域对照与性能口径

  • 海外节点必须核对实际国家、ASN 与接入网标签。固定同一组探针同时测公共对照、目标 API 与 DNS,不能把其他国家云机当作家庭现场。公共探针 UA、账号状态、代理出口和同运营者标签均影响证据范围;DNS 能解析或 CDN 根路径 403 都不能代替签名媒体 Range 测试。
  • 检测包只导出国家、BVID、目的域名/IP、HTTP/业务状态和耗时,不导出源 IP、Cookie 或签名 URL。真实 HTTP fixture 要覆盖错范围、403、停滞响应体和进程不可用;失败仍需留下报告。
  • 长播逐项区分播放、主站/直播 API、第三方更新源与后台 uptime。首个失败之后继续观察恢复和其他通路,保留最终失败状态,不要用 fail-fast 丢掉历史故障时间窗。
  • performance.memory 可能量化为固定值;使用 CDP Runtime.getHeapUsage 测 JS 堆并注明不含 GPU/进程总内存。按键到 DOM MutationObserver 与双 rAF/屏幕绘制不同,不直接比较或相减。稳态长任务不包含起播阶段,短机型样本也不能证明所有设备无泄漏或无优化空间。

2026-10-13:长订阅清理必须穿过 SDK

  • cancelled=true 只能停止应用交付,不能释放 webOSTV.js 模块内保存的长订阅请求与 PalmServiceBridge。本轮弹幕/投屏两条路径各循环 20 次,真实 SDK fixture 旧版 0 次 cancel、新版 20 次。保存 request 句柄,退出先关闭回调交付再幂等 cancel;danmakuStop 只负责服务中继,不能替代 SDK cancel。
  • 资源测试使用完整生产模块和项目附带 SDK,仅 stub 平台桥边界,不用自写 request 替身证明 SDK 内部行为。SDK 用 Date.now 作保存键,本地紧循环 fixture 需保证时间戳递增,避免同毫秒覆盖让泄漏数量失真。异常 cancel/无句柄只证明清理不崩、迟到回调被忽略,不宣称底层资源释放。
  • 直播 HLS 的初始 currentTime 可能很大;起播验收监听真实 playing 后再累计后续正向时间推进。退出后分别核对 SDK cancel、服务 stop、订阅数量和迟到 DOM;导出帧数/状态码,不导出聊天、token、标题或签名源地址。

2026-10-13:异步切源与同页资源耐久

  • 倍速切换有“等待 URL”和“等待 unload”两个取消边界。两处都延迟再执行退出/新视频/1x/新倍速/画质切换,核对旧 video 是否仍被赋 src 或调用 play;只测最后 DOM 不足以发现已脱离 DOM 的媒体复活。取消旧意图不能让新意图丢失:unload 已开始时选 1x 必须重新装载 DASH。倍速请求代次与当前 DASH 的有效生命周期分开,单纯选择正常速度不应废掉仍在播放的流的故障回退。

  • 机翻退出不能仅屏蔽 setState。让已发出的四个翻译请求在退出后返回,检查后续批次和重试是否仍被排队;再让字幕正文在退出后首次返回,检查是否从零启动整轨翻译。正常译文、顺序、cache 和 LRU 仍要通过。区分“停止新增批次”与“取消在飞 HTTP”,前者不能描述成后者。

  • 真机重复进入/退出必须在同一个 document;保留自然与统一强制 GC 后指标,明确后者不含 GPU/进程 RSS。destroy wrapper 仅保留计数,不能用全局数组保存旧 player/video 制造假泄漏。CDP 总节点不等于 detached 节点,HTTP 在飞数也不等于 Luna/后台所有连接。

  • 遥控耐久前后采用相同路径,保存至少 30 个实际焦点变化与 from/to,比较同一口径 p95。key capture 监听器和 MutationObserver 必须具名归属、finally 断开,然后再做堆/监听器采样;失败样本也保留。用 Chromium 夹具强制中途失败,证明工具清理确实执行;夹具不能把浏览器自动化自身的 observer 误算成工具泄漏。

  • 资源测试的最终退出、恢复偏好、移除注入应分开 try,不能因 Back 失败就跳过后两项。构建/源码变动后长播重新计时,旧包基线不能拼入新包验收时长。

  • 同一 unload 内再次选择倍速且新取流失败,要分别让失败先于/晚于 unload 完成;旧版 UI 回到 1x 不代表 DASH 已恢复。复用卸载 Promise,并在卸载前记录位置/暂停;所有恢复 load 等旧 unload 结束后再检查当前意图。共享卸载的更新 native 意图也必须使插入的 1x/画质意图失效,覆盖 2x→1x 等待→1.5x。

  • native 已赋源但 metadata 未到时,currentTime 可能为 0。播放快照不能在赋 src 后立即清空,应等 seek 真正应用;测试回 1x 恢复原位置与暂停。加载遮罩会拦鼠标,电视仍可用的遥控路径应以真实按键驱动,不用 force click 冒充可达 UI。

  • 从应用手动设置的 native src 交回 Shaka 时,不能假设其 load 一定先 unload:此前卸载可能已清掉内部 assetUri。native 旧 readyState/currentTime 可能让新 playhead 错认为已定位,随后新 metadata 归零。暂停态往返应同时核对 load 参数、load 完成、metadata/canplay、最终 currentTime,不能只检查参数或 blob+ready4;必要时先共享并等待显式 native detach,保留原位置/暂停与代际取消,避免盲目追加 seek。平台边界模型要标明为模型,真机时间线另证。

  • 直播聊天 event/frame 数不能代表媒体重试或服务内部 WS 重连。沿既有诊断通路只记录安全类型/次数/相对时间,处理字段展开覆盖事件名的历史格式;恢复原数组 push 和服务 request 包装,失败也执行清理。实际模块的受控 WebSocket/时钟测试可以证明重试预算与 stop guard,不能写成电视连接测量;首次成功数据重置预算的行为、已排队 timeout 只在触发时被 closed guard 拦住的行为都应准确陈述。

2026-10-13:耐久必须检查中途交付

  • 真机直播在前 4 分钟收到 216 条弹幕/956 个事件,随后到第 15 分钟不再增长;“累计收到过数据”和“stop 函数还在”仍让旧工具全部通过。总量不能代表连续健康,必须记录最后到达时刻及连接实际状态。
  • 安静房间不能当断流:用相同房间的只读历史接口,只保存条数和最新时间,确认独立源持续产生新消息后再判 relay 交付停止。不要保存聊天正文/昵称,也不要新建同账号 WS 挤掉被测连接。
  • 原始工具 PASS 不改写;另存人工复核 FAIL 与漏检原因,并补能复现的判据测试。现场没有 socket/protocol 诊断时,只能确认交付停止;源码中的可复现机制不等于现场根因已证实。

2026-10-13:连接释放和观测边界的正对照

  • 旧 WebSocket 库的 terminate 在 CONNECTING 期间可能不 abort 底层请求,OPEN 状态也可能等待关闭握手。验证必须使用真实旧库与真实客户端 request/socket;只用假的 WS 计数不能证明资源释放。对允许 half-open 的夹具,以客户端 destroyed/close 为准,不能把服务器自己保留的半开端误判为客户端泄漏。
  • 重试预算必须区分连续失败与整段会话累计失败。长看中累计几次健康重连后永久停止,会让短测正常、耐久断流。心跳响应应独立于聊天事件;安静房间没有聊天不等于连接已死。
  • 暂停保持位置要同时检查仍 paused 和绝对时间差。只有 after-before<阈值,会让大幅倒退以及未暂停也误过;用旧谓词真实误判与修后拒绝作工具正对照。
  • API JSON 解析失败要保留 HTTP 状态、体长度/固定格式分类,服务失败只保留安全类别与数值码。单个 failed:true 不足以区分网络、服务器非JSON响应和工具解析;缺失字段不能靠之后成功的补测回填。

2026-10-13:恢复边界与堆增长归因

  • CDN 隔离要测全部候选均失败:只选第一个未隔离节点、否则回主节点,会在最后一次主节点失败后一直重试主节点。失败历史按时间去重,全部失败时选最早失败的可用节点,保留 API 原签名与画质;格式/解码错误和网络错误分开。
  • 直播 watchdog 的判据应区分空缓冲、有缓冲、暂停/seek、取源中和终止。重试赋源时间不能写成真实解码恢复时间;保存旧边界失败与修后通过,阈值包含轮询间隔和重试退避。
  • 堆增长先拆分 V8 code、自有对象形状、DOM/监听器和调试保留。开发模式固定容量性能桶预热也会增长;采样延长到容量填满之后,不能仅看前 20 次斜率。原始 heap snapshot 可能含账号与签名地址,只存本机私有目录,公开数值聚合。浏览器受控解码器的归因不能代替电视 Shaka/硬件实测。

2026-10-14:自动画质偏好与真实媒体就绪

  • 区分用户画质偏好与本片实际 qn;自动因设备/权限选择较低档不应把偏好写成手动。倍速恢复等内部重载不能覆盖显式选择。旧默认与旧手选无法区分时,迁移规则必须明说,新增手动标记;固定画质测试工具同步设置该标记。
  • Shaka load 返回后,active track 与 MPD 可能已更新,但 video.readyState、尺寸和时钟尚未准备好。切档验收同时等媒体就绪和真实时间推进,不能在设置刚写入时以 width=0 判解码失败;原始误判保留,同包重测,不用改播放器来迎合采样时机。
  • 会员标识用 nav 的登录、状态、类型和到期信息,不能从 Cookie 或质量档位标签推断。AAC 是否选错先看同一会话同一视频 API 的完整音轨集合,并以含 E-AC-3 的真实片源作正对照。

2026-10-14:实体屏幕与失败现场

  • SSH/CDP 可连接、页面 visible/focused、截图和解码计数都不能单独证明实体面板已点亮。电源查询被拒绝时如实记录,需人工确认亮屏;不要称为完整画面验收。
  • 真机用例失败应在 finally 退出播放器/恢复设置之前保存 codec、readyState、进度、暂停、焦点/弹窗及错误状态。一次重跑通过不能替代首次失败原因分析;保留失败证据。

Version History

  • 2af1277 Current 2026-10-18 20:03

    语法检查从ES2017调整为ES5以适配Node 0.12;新增webOS 5/6兼容性说明及真机工具箱文档。

  • e11caa1 2026-07-19 10:53
  • a0fc167 2026-07-11 17:45

Metadata

Files
0
Version
2af1277
Hash
c61e6dc4
Indexed
2026-07-11 17:45

홈 - 위키
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-10-24 11:17
浙ICP备14020137号-1