Files
live-caption/docs/testing.md
T
blumia d234b9658d docs: refresh docs to match the current state, add GUI/CLI/troubleshooting
The README still listed the settings UI as "todo" and its quick start told
users to download models into the working directory; phase 3 still described
the caption window's close button as "quit" and used the wrong binary name.
Bring the docs up to date and fill the gaps: a GUI guide (first run, settings
tabs, tray, download, verify), a full CLI option reference marking the
test-only flags, a troubleshooting page, the model registry's size/sha256
fields plus a licence/size table, the RTF measurement caveat (llama-cli 0.19
vs the in-process 0.56), and a note that the streaming-ONNX backend has its
own code path. phase0/phase1 experiment docs are marked as historical.

文档与现状对齐:README 的 Phase 4 从「待做」改为完成、快速开始不再让人把模型下到当前
目录;phase3 的 ✕ 说明改为「隐藏到托盘」、用法改用 live-caption;新增 GUI/CLI/排错三份
文档;asr-backends 补上注册表的 size/sha256 字段与模型许可/体积表;phase0 补上 RTF 口径
说明(llama-cli 的 0.19 与程序内的 0.56);phase2 补上「流式 ONNX 走另一条分支」的说明。
2026-10-12 17:29:45 +08:00

4.9 KiB
Raw Blame History

测试

分层

目标 依赖 说明
livecaption_core 无 Qt 全部业务逻辑;单元测试只依赖它
livecaption_models Qt6::Core / Network 注册表、安装检查、sha256 校验、应用内下载
livecaption_ui Qt6::Widgets 悬浮窗、设置对话框、Qt 适配层
live-caption ui + models 悬浮窗程序
live-caption-cli core + models + Qt6::Core 命令行程序(不链接 Qt Widgets)
tst_* core + Qt6::Test 单元测试

运行

cmake -S . -B build && cmake --build build -j
ctest --test-dir build --output-on-failure    # 也可以单独跑 build/tests/tst_xxx

单元测试不需要模型文件,也不需要显示环境,秒级完成。目前 4 套:

测试 覆盖
tst_streamingasr 流式策略:拼接、分段、已稳定/不稳定尾部、冷启动前缀
tst_livepipeline 实时管线:静音过滤、不规则 chunk 不丢样本、静音分段
tst_vad 能量 VAD(轻话音的检测)
tst_transcript 输出解析与语言名映射

为什么能这样测

关键是把推理后端抽象成 IAsr(src/core/iasr.h),测试里换成 tests/fakeasr.h 的 FakeAsr:

  • 可以脚本化每一次 streamAppend 返回什么文本;
  • 记录每次拿到的前缀、音频样本数、以及 streamReset 的调用次数;
  • dropLastTokens 用"空格分词"模拟词表,并保留原有格式。

另外 LivePipeline 刻意不带 Qt 依赖、并且把「送音频」拆成同步的 process(),所以测试可以直接喂音频,不必碰 PulseAudio。

覆盖的回归用例

这些用例对应的都是开发过程中实际踩到的坑:

测试 对应的坑
tst_streamingasr.keepsJoiningSpace 用 trim() 过的文本拼接,导致续写缺空格(potatoesand)
tst_streamingasr.segmentsAccumulateWithoutLosingEarlierText 多段拼接时只保留最后一个语言头之后的内容,前面正文丢失
tst_streamingasr.committedDropsUnstableTail 已提交 / 不稳定尾部的划分
tst_streamingasr.flushCommitsEverything 流结束时尾部被丢掉
tst_streamingasr.coldStartHasNoPrefix 冷启动阶段不应回喂前缀
tst_livepipeline.silenceIsNotForwarded 静音被送进模型导致幻觉(英文语音前冒出 嗯。)
tst_livepipeline.noSamplesDroppedAcrossIrregularChunks 工作线程丢样本(余数没接上),造成假静音与截断
tst_livepipeline.silenceEndsSegment 静音收束分段
tst_vad.quietSpeechIsDetected 噪声底用均值跟踪,把很轻的话音全判成静音
tst_transcript.* 输出解析与语言名映射

写测试的过程中还抓到一个真 bug:段恰好结束在 chunk 边界(没有待处理音频)时,flush() 只提交"已稳定"部分,最后几个词会被丢掉。已修(用完整文本 lastRawFull_ 提交)。

界面 / 集成测试钩子

界面与真实音频链路不做单元测试,但留有可脚本化的入口(全部选项见 cli.md):

# 设置对话框各条退出路径的冒烟测试(当初定位「点确定就退出」的崩溃就是靠它)
for how in reject close accept ok apply; do
  ./build/live-caption --asr-model zipformer-zh-2025 --no-tray \
      --settings-autoclose $how --quit-after 8
  echo "$how → 退出码 $?"
done

# 界面渲染自截图(折叠态 + 展开态),不依赖外部截图工具
./build/live-caption --asr-model zipformer-zh-2025 --no-tray \
    --screenshot /tmp/win.png --screenshot-delay 6
./build/live-caption --screenshot-settings /tmp/settings.png

# 模型完整性与采集设备(不需要显示环境)
./build/live-caption-cli --verify-model zipformer-zh-2025
./build/live-caption-cli --list-devices

崩溃时用 coredumpctl list / coredumpctl info <PID> 看调用栈。

尚未覆盖

以下几类需要真模型或真实音频设备,属于集成测试,没放进单元测试:

  • 8s 编码切片对齐:这是准确率的决定性因素(切 2s 会明显掉准确率),但必须用真模型跑才能验证。
  • 增量 KV 复用的单步延迟:需要真模型才能测。
  • 采集链路(PulseAudio/PipeWire 的 monitor 源、设备枚举)。
  • GUI 渲染的像素级断言(目前只有人工看截图)。

这些目前靠 experiments/ 下的脚本与实机验证(见 docs/phase0..3)。

后续可加

  • 给需要模型的集成测试打 CTest label(如 model),默认跳过,用环境变量指模型路径时才跑。
  • GUI 的渲染回归:已有的 --screenshot 自截图,可以断言面板像素 alpha((0,0,0,214)),避免再次出现"样式表背景对自定义 QWidget 不生效 → 明明想半透明结果全透明"这类问题。
  • 给 ModelStore::verify 加一个用临时文件构造损坏模型的单元测试(现在只在集成层面手工验证过)。