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 边界时 只提交了稳定部分,最后几个词被丢掉,已修。
This commit is contained in:
1 parent
4ed4e23282
commit
736ec14d5b
32 files changed
+1502
-655
No files matched your search
@@ -0,0 +1,65 @@
|
||||
# 测试
|
||||
|
||||
## 分层
|
||||
|
||||
| 目标 | 依赖 | 说明 |
|
||||
|---|---|---|
|
||||
| `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 不生效 → 明明想半透明结果全透明"这类问题。
|
||||
Reference in new issue
Block a user