Hypium 单元测试实战:为什么 exit code 0 不代表测试通过

测试写到一定规模,工具链的信任问题就成了头等大事。这个项目最终积累了 418 条 Hypium 用例(全绿基线),但比用例数量更重要的是围绕执行建立的一套纪律——因为我们很早就被工具链坑过一次狠的。
1. 头号陷阱:Hvigor 的 exit code 会撒谎
把这个坑放在最前面,因为它能悄无声息地废掉你的全部测试:
Hvigor 在 Hypium 断言失败时可能仍返回进程码 0。
也就是说:hvigorw test 跑完,echo $? 是 0,日志里却躺着 failed 的用例。如果你的 CI 或验收脚本靠退出码判断——恭喜,你的红灯永远是绿的,测试烂掉半个月都没人知道(我们就是翻了 Hvigor 日志才发现)。
权威判定必须读测试结果文件:
hvigorw --mode module -p product=default -p module=entry@default test --no-daemon
cat entry/.test/default/intermediates/test/coverage_data/test_result.txt
test_result.txt 里才是真实的通过/失败/忽略计数。我们的所有验收脚本都解析这个文件,退出码只作为参考。这条规则写进了项目交接文档的常用验证区,加粗置顶——工具链的默认信号不可信时,把真相来源写成肌肉记忆。
2. 三层区分:构建成功 ≠ 测试执行 ≠ runner 通过
上一个坑的泛化形式,是验收汇报里常见的三种"假绿":
-
构建成功:HAP 打出来了。和测试没有任何关系。
-
测试编译通过:测试代码编进了测试包。一个用例都没跑也可能是这个状态。
-
runner 执行且断言通过:
test_result.txt里的数字作证。
项目规则要求汇报时严格区分这三层:"测试通过"只能指第三层,且必须给 test_result.txt 的数字(我们的口径:418/0/0 = 通过/失败/忽略)。这个区分的价值在协作:验收方拿到"构建成功"的汇报就知道要打回,而不是默认测试也过了。
3. 用例组织:按模块分文件,命名即索引
418 条用例如果堆在一个文件里就是灾难。测试目录按被测模块一一对应:
entry/src/test/
├── SpeakLabPromptContracts.test.ets # B14 的 Prompt 契约
├── SpeakLabAsrAdapter.test.ets # B10 的 ASR 适配层
├── SpeakLabNavigationContract.test.ets # B04 的导航策略纯函数
├── SpeakLabStreamReleaseGate.test.ets # B13 的流式时序门
├── SpeakLabAiMemoryCredential.test.ets # B15 的凭据控制器
├── SpeakLabAnalysisPresentation.test.ets # B06 的呈现投影
└── …
找测试和找被测代码是同一个词。新增模块时测试文件同步创建,这条对称性让"这个模块有没有测试"变成一眼可查的事。
4. 可测性的源头:依赖注入是设计出来的
回看前面几篇,几乎每个模块都有一句"纯函数/可注入":这不是为了优雅,是为了这些模块今天能在 Hypium 里脱离设备被测。例子:
-
ASR 适配层(B10):构造时注入 platform port + 调度器 + 时钟,测试用 fake port 驱动 VAD 完结、错误风暴,断言续接与回调隔离;
-
生命周期(B12):TrainingFlow 的四个生命周期方法直接调用,断言 ASR release / AI dispose 被触发;
-
导航策略(B04):纯逻辑栈
SpeakLabLogicalNavStack,导航不变式零 UI 断言; -
分词算法(B08):纯函数 + Node oracle 对拍。
模式一句话:难测的副作用(系统 Kit、时钟、IO)全部挤到 port 接口后面,构造期注入。测试不是写完代码再补的事,是写代码时就决定了接口形状。
5. 测试基建的杂项经验
-
--no-daemon:CI/验收环境关 Hvigor 守护进程,避免缓存状态污染结果; -
SDK 路径:
DEVECO_SDK_HOME指到Contents/sdk(B01 讲过),测试和构建共用这条; -
hamock:
@ohos/hamock在 devDependencies 里备用,但优先用"构造注入 fake"而不是 mock 框架——fake 是显式代码,行为可审查,mock 框架的魔法在排查时常常帮倒忙; -
每个阶段任务冻结测试基线数字:418 不是一路随缘涨上来的,每个阶段关单时"累计 X 条、0 失败"是验收项,数字本身被冻结进任务单。
6. 小结
-
Hvigor 断言失败也可能 exit 0;唯一权威是
test_result.txt,验收脚本必须解析它。 -
汇报三层区分:构建成功 / 测试编译 / runner 通过,互相不能替代。
-
用例按模块分文件,命名对称;可测性来自构造期依赖注入,不是事后补。
-
测试基线数字随阶段冻结,成为验收项。
更多推荐



所有评论(0)