Files
blumia 898763eb74 fix(gui): drop a dead setting, make the language list and tail toggle real
Three settings were only half-wired:

- autoPickByLanguage was saved but never read anywhere: delete it.
- showUnstableTail had a checkbox and a setter, but nothing ever called
  the setter, so the checkbox did nothing: apply it in applyAppearance
  and re-render from the cached text instead of blanking the caption.
- the language dropdown was hard-coded to auto/zh/en/ja while the registry
  declares up to 16 languages per model: build it from the selected
  model's own language list, with an ISO-code to display-name mapping
  (plus a unit test covering every code in the registry). The caption
  window's language pill now follows the setting too, instead of keeping
  whatever it showed at startup.

windowPos is not dead -- it stores the dragged window position -- so it stays.

三个「半死」设置:autoPickByLanguage 存了但从没被读取,直接删掉;showUnstableTail
有复选框也有 setter,但从来没人调用 setter(复选框点了没用),改为在 applyAppearance
里生效并用缓存文本重画;「识别语言」下拉原来硬编码 自动/中/英/日,而注册表里每个模型
声明了最多 16 种语言,改为按所选模型的语言动态生成,并补 ISO 码→显示名映射与单元测试。
字幕窗的语言标签也跟着设置走了(原来只在启动时读一次)。windowPos 不是死设置(它存的
是拖动后的位置),保留。
2026-10-12 17:48:21 +08:00

100 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 测试
## 分层
| 目标 | 依赖 | 说明 |
|---|---|---|
| `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 | 单元测试 |
## 运行
```bash
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.*` | 输出解析与语言名映射 |
| `tst_transcript.isoCodeDisplayName` / `registryLanguagesAllHaveDisplayNames` | 设置里的语言提示用的是 ISO 码(`zh`/`uk`…),漏了显示名的话「识别语言」下拉会直接露出 `uk` 这种码 |
写测试的过程中还**抓到一个真 bug**:段恰好结束在 chunk 边界(没有待处理音频)时,`flush()` 只提交"已稳定"部分,最后几个词会被丢掉。已修(用完整文本 `lastRawFull_` 提交)。
## 界面 / 集成测试钩子
界面与真实音频链路不做单元测试,但留有可脚本化的入口(全部选项见 [cli.md](cli.md)):
```bash
# 设置对话框各条退出路径的冒烟测试(当初定位「点确定就退出」的崩溃就是靠它)
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` 加一个用临时文件构造损坏模型的单元测试(现在只在集成层面手工验证过)。