直接回答
Fake 推理引擎是应用侧接口的可控测试实现,不是 LiteRT-LM 的缩小版。本仓库的 AiInferenceEngine 定义七个返回 Flow<String> 的方法,EngineProvider 则是一个挂起函数,返回 Result<AiInferenceEngine>。Fake 应实现这些准确的方法,并允许测试为每个请求指定结果序列或失败;不能擅自给接口加 initialize、close、cancel、引擎状态、后端选择或 native 资源方法。这些操作属于具体运行时所有者,并不在当前公共 Fake 接口中。 先验证冷流边界。收集前不应运行 producer 脚本、执行假推理或增加执行/收集计数。Fake 可以在方法创建 Flow 时记录 API 调用;要把这种工厂调用日志与 producer 执行计数分开。开始收集才触发 Fake 行为,这与接口文档的冷流约定一致。把行为明确分成:立即返回一组值、空流、延迟值序列,或先发部分结果再在指定点抛错。每种情形都要断言收集到的值和终止方式。只检查 Flow 对象非空,并不能证明收集会工作、预期值会到达或异常会传到调用方。 用 Fake 让事件顺序可重复。脚本可以先发一段部分文本,在一个测试可控位置暂停,再发最终片段并结束;另一个脚本可以在首个值前失败,或在部分输出后失败。记录请求方法、参数、收集次数和结束状态。每个脚本只回答一个问题。若输入夹具包含提示词或转录,使用合成内容,只比较接口契约需要的输入,不把生产用户文本写进调用记录。 协程虚拟时间可以让延迟流变得确定。使用 kotlinx-coroutines-test 时,在 runTest 下运行被测对象,并通过共享 TestCoroutineScheduler 推进 Fake 延迟。Fake 延迟应使用测试提供的调度器。如果生产代码把 Flow 移到 Dispatchers.Default,虚拟时间不会自动控制那个调度器;此时要么在所有者处注入 dispatcher,要么把该真实调度行为留给其他测试。不要用真实 sleep 等待某个事件大概发生;应等待命名事件,或把调度器推进到测试掌握的时刻。 取消结论必须写准确。AiInferenceEngine 没有显式取消方法;应用取消的是正在收集 Flow 的协程 Job。协作式 Fake 可以在两次发射之间挂起,并记录收集因取消而结束。这样能验证 ViewModel 停止消费后续值、不把部分响应呈现为完成状态,以及允许后续请求继续。它不能证明真实 JNI 调用或 LiteRT-LM native generation 已停止、释放内存或关闭 conversation。这些需要独立的真实运行时测试及具体 adapter 的证据。Fake 不应捕获 CancellationException 后继续发射,否则会掩盖问题,而不是遵守契约。 Provider 失败与推理失败也要分开测试。EngineProvider 可以在引擎创建前返回 Result.failure;引擎方法则可能在 Flow 被收集时抛错。断言调用方对两种边界显示不同状态,且在引擎不可用时没有调用方法。还要测试空流成功,因为没有输出不等于 provider 失败。如果 UI 允许第二次提交,应给请求绑定 ID,验证旧脚本延迟到达的事件不能覆盖新请求状态。 并发预期要限定在接口契约和被测组件内。当前 InferenceEngine 用互斥锁串行化推理,AiInferenceEngine 文档也说明同一实例一般不应并发调用。Fake 可以记录重叠收集,帮助测试 ViewModel 按应用策略排队或拒绝第二项工作;但 Fake 恰好串行执行,不等于具体引擎也具备该保证。若生产串行化是必要条件,应另测真实实现或明确指定的 adapter 契约。 保持 Fake 小而有脚本能力即可,不必做成完整测试框架。可提供每个方法的结果脚本、只记方法名和请求 ID 的调用日志、测试可释放的门闩,以及当前收集器数量。不要把大图像或音频缓冲区复制进调用日志。断言应回答应用是否调用指定方法、是否观察到预定值和终止事件、是否处理了后续状态,而不是评价生成语言质量或替代模型基准。 当前 InferenceEngineTest 为 processText 和 transcribeAudio 创建 Flow,但只断言 Flow 非空。这能证明 Flow 对象被构造,不代表收集时会发射结果。新增 Fake 测试能补充应用消费者契约的证据。结论仍应严格限定:Fake 只证明被测消费者如何处理这些脚本化输入与事件;它不证明真实运行时接受同一提示、流式行为完全一致、native 取消生效,或翻译、摘要、转写正确。
第一条流还在生成时,ViewModel 收到第二个请求
用户提交本地摘要,首段文字出现后又编辑输入并再次提交。团队想在不加载模型的情况下检查事件归属和取消行为,同时不把 Fake 收集器取消说成 native generation 已停止。
决策
注入一条在部分值后暂停的 AiInferenceEngine 脚本,按产品策略取消或替换旧请求,再断言只有当前请求的事件能更新状态。
预期结果
ViewModel 测试能证明受控 Fake 下的请求状态行为;native 取消、资源释放和输出质量仍需单独验证。
需要收集的证据
只有将以下证据与同一模型文件和测试运行关联起来,结论才可复核:
- COVE-LIFECYCLE-01:当前 ModelManager 暴露模型状态并管理引擎获取;该事实不证明真实 native generation 对协程取消的响应。
- BENCHMARK-01:仓库没有完整真机基准数据;Fake 结果只支持被脚本化的消费者契约,不构成设备、速度或质量结果。
发布结论只对所记录的配置和验收集有效;扩大适用范围需要更多记录。
实施流程
- 按接口实现 Fake. 实现七个 AiInferenceEngine Flow 方法及 EngineProvider 的 Result 返回路径。不要给接口增加不存在的 native 生命周期方法;在 Fake 边界记录调用和可控结果脚本。
- 验证冷流收集. 将方法工厂调用日志与 producer 执行/收集计数分开。断言 collect 前脚本尚未运行,再检查发射值和终止事件。
- 编写成功与失败脚本. 覆盖多个值、空流成功、provider Result.failure、Flow 立即异常及部分值后失败。确认调用方形成目标状态,同时不把私密夹具写进日志。
- 控制延迟与协作取消. 用 runTest 和共享调度器推进 Fake 延迟,在确定的事件点取消,并断言后续值不再被收集。结论限定为 Flow 收集行为。
- 检查请求身份和竞争事件. 用门闩按指定次序释放新旧请求事件,确认活动请求拥有界面结果;Fake 不作为真实引擎并发安全的证据。
- 写明证据边界. 记录 Fake 实现、脚本、收集器和调度器、断言及未覆盖的真实运行时行为。不要将 native 初始化、close、硬件后端或任务质量归入 Fake 结论。
让每个阶段的状态都可观察。失败信息应指出阶段、模型、运行时和恢复动作,同时避免记录用户私密内容。
验收标准
- 测试会收集 Flow 并断言发射值、空流成功、provider 失败和收集期间异常,不只检查 Flow 非空。
- 取消发生在确定事件边界,报告描述为协作式收集行为,不声称 native 引擎已取消。
- Fake 精确实现当前接口,不增加原生初始化、关闭、后端选择或模型质量的保证。
决策对照表
| 维度 | 选择或证据 | 解读方式 |
|---|---|---|
| Fake AiInferenceEngine | 脚本化 Flow 值、时序和错误 | 快速确定地验证消费者和接口契约,不执行真实运行时。 |
| InferenceEngine 单测或集成测试 | 用真实兼容制品收集真实实现 | 可观察 adapter/运行时行为,但需要 native 依赖和制品环境。 |
| 设备任务评估 | 在指定构建和设备运行版本化任务夹具 | 可支持有限任务或资源结论;Fake 和单次输出都不能证明通用质量。 |
需要避免的失败模式
- 只断言返回 Flow 非空,不收集并验证值、结束方式或错误映射。
- 把 fake 收集器收到取消当成 LiteRT-LM native 推理已经停止或释放资源的证明。
还要避免静默回退、版本未固定、缺少取消处理,以及把不同配置的结果混在一起下结论。失败运行也应与成功记录一并保存。
最小复现记录
| 层级 | 记录内容 |
|---|---|
| 设备 | 厂商、型号、芯片、内存档位、操作系统版本 |
| 软件 | 应用版本和 Git 提交号 |
| 模型 | 系列、变体、版本、格式、文件长度、摘要、量化方式 |
| 运行时 | 名称、版本、请求后端及实际后端证据 |
| 工作负载 | 样例版本、输入摘要、提示词摘要、输出策略 |
| 结果 | 完成、失败、取消、回退及保护隐私的诊断信息 |
发布检查表
- ☐ 主要搜索问题已回答,且没有未经支持的数字。
- ☐ 所有模型文件和运行时版本均已固定。
- ☐ 代表性任务和失败处理策略均有说明。
- ☐ 生命周期、取消、清理和回退均已测试。
- ☐ 用户内容与网络边界均有说明。
- ☐ 结论只适用于被记录的配置。
- ☐ 新增测试结果时链接到原始方法或证据。
来源与相关证据
- Cove 基准测试方法
- Android Developers:在 Android 中使用测试替身
- Kotlin Coroutines:kotlinx-coroutines-test 与 runTest
- Android Developers:测试基础
中文部署与排错专题见。奇连 AI 端侧专题。
常见问题
取消 Fake Flow 能证明 LiteRT-LM 停止生成吗?
不能。它证明收集器和测试替身响应了协程取消。native 工作、内存释放和 conversation 关闭需要真实运行时测试及具体 adapter 证据。
Fake 应该实现 initialize 和 close 吗?
不应加到 AiInferenceEngine 上,因为当前契约包含七个推理方法,没有 initialize 或 close。应在实际拥有这些操作的 ModelManager 或具体运行时边界测试生命周期。
断言返回的 Flow 非空够不够?
不够。需要收集它,并断言值、终止状态、错误映射和相关状态变化。Flow 对象被构造并不能说明会发射或调用方处理正确。