Files
live-caption/docs/testing.md
T
blumia 736ec14d5b refactor: split core/ui/apps targets and add unit tests
Move all business logic into liblivecaption_core (no Qt dependency) and
the widgets into liblivecaption_ui, leaving two executables: the caption
window and the CLI, which no longer links Qt Widgets. Abstract the ASR
backend behind IAsr so the streaming policy and the live pipeline can be
tested with a scripted fake backend instead of a real model.

把全部业务逻辑下沉到不依赖 Qt 的 liblivecaption_core,界面独立成
liblivecaption_ui,拆出悬浮窗与命令行两个可执行程序(CLI 不再链接 Qt
Widgets);并用 IAsr 抽象推理后端,使流式策略与实时管线可脱离真模型
用假实现做单元测试。测试还抓到一个真 bug:段恰好结束在 chunk 边界时
只提交了稳定部分,最后几个词被丢掉,已修。
2026-10-12 13:43:50 +08:00

66 lines
3.3 KiB
Markdown
Raw 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_ui` | Qt6::Widgets | 悬浮窗与 Qt 适配层 |
| `live-caption` | ui | 悬浮窗程序 |
| `live-caption-cli` | core + 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
```
单元测试**不需要模型文件,也不需要显示环境**,秒级完成。
## 为什么能这样测
关键是把推理后端抽象成 `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_` 提交)。
## 尚未覆盖
以下几类需要真模型或真实音频设备,属于集成测试,没放进单元测试:
- **8s 编码切片对齐**:这是准确率的决定性因素(切 2s 会明显掉准确率),但必须用真模型跑才能验证。
- **增量 KV 复用的单步延迟**:需要真模型才能测。
- 采集链路(PulseAudio/PipeWire 的 monitor 源)。
- GUI 渲染。
这些目前靠 `experiments/` 下的脚本与实机验证(见 `docs/phase0..3`)。
## 后续可加
- 给需要模型的集成测试打 CTest label(如 `model`),默认跳过,用环境变量指模型路径时才跑。
- GUI 的渲染回归:已有的 `--screenshot` 自截图,可以断言面板像素 alpha(`(0,0,0,214)`),避免再次出现"样式表背景对自定义 QWidget 不生效 → 明明想半透明结果全透明"这类问题。