CANN Runtime 仓 UT 用例开发指导:从设计 checklist 到源码级实践
发布时间:2026/9/18 12:42:15 作者:尧图编辑部 阅读量:1,286

CANN Runtime 仓 UT 用例开发指导从设计 checklist 到源码级实践【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime本篇技术指南聚焦 CANN Runtime 开源仓库cann/runtime中 UT 用例的开发方法论与工程实践以docs/zh/guidelines/dt_guide/ut_case_development_guide.md为骨架结合仓库内真实测试代码展开。读完本文你将掌握 Runtime 仓 UT 的设计要点输入校验、边界值、资源生命周期、全局状态等、如何做完整校验、mock 与全局状态的收口规范、私有成员访问边界、文件系统隔离以及兼容性测试的落地位置并能在tests/目录下独立写出合规、可维护、可回归的用例。一、UT 的定位与测试范围在 Runtime 仓中UT单元测试的测试范围通常是一个文件、一个类或者一个边界清晰的函数集合。UT 的重点是隔离被测对象验证其对外可观察行为而不是顺带验证整条链路上的所有模块。这一点决定了 UT 用例的设计方式被测对象之外的依赖驱动接口、系统调用、日志、单例等应当通过 mock、桩或 stub 隔离掉用例只回答这个函数在给定输入下是否产生了正确的可观察结果这一问题。反之如果某个场景已经跨越模块边界需要启动模拟器、设备环境或完整流程通常更适合放到 ST系统测试而不是继续堆在 UT 中。Runtime 仓没有单独的tests/st目录ST 往往与对应模块放在同一棵tests/ut/**目录树下常见位置如tests/ut/msprof/st、tests/ut/platform/st、tests/ut/adump/st参见 DT用例开发总纲。二、UT 用例设计 checklist为某个接口设计测试点时建议优先逐项检查以下内容与当前接口无关的检查项可以不强行设计用例2.1 外部输入校验空指针接口入参为nullptr时应返回明确的错误码而非崩溃。例如tests/ut/acl/testcase/acl_queue_unittest.cpp中acltdtSetQueueAttr(nullptr, ACL_TDT_QUEUE_NAME_PTR, len, name)直接断言返回ACL_ERROR_INVALID_PARAM。非法枚举值超出枚举定义范围的输入。越界长度、容量、索引例如acltdtSetQueueAttr中len与属性类型不匹配、缓冲区越界等情况。不满足前置条件的句柄或状态未初始化、已销毁、非本 device 上下文中的句柄等。2.2 边界值空容器、零长度、最小/最大合法值单元素与多元素场景。例如队列属性默认值场景中acltdtCreateQueueAttr创建出的属性应校验depth默认值等于 8、workMode等于RT_MQ_MODE_DEFAULT等初始状态见 acl_queue_unittest.cpp。2.3 资源生命周期申请和释放是否配对create 与 destroy 成对出现失败路径是否有泄漏mock 让底层申请失败时上层是否仍正确释放重复创建、重复释放是否安全幂等性。2.4 全局状态与单例rtSetSocVersion、SetChipType、rtSetDevice等全局状态切换环境变量、配置开关、静态缓存是否需要恢复。这是 Runtime 仓 UT 最容易踩坑的地方Runtime 内部大量依赖全局的单例如 context、device 管理、队列管理器用例一旦修改了这些状态而没有恢复就会污染后续所有用例。从源码结构看src/runtime/下大量模块都是通过全局单例管理器对外暴露能力的因此改状态必恢复是一条硬约束。2.5 平台/芯片分支同一接口在不同 SoC、不同 driver 能力下是否有分支行为。Runtime 仓测试中可以看到大量按平台组织的用例例如 tests/ut/runtime/runtime/test/platform/910B/ 下的rt_utest_api.cc等文件都包含SetChipType相关的全局状态操作需要在用例结束后恢复。2.6 回调与副作用回调是否注册/触发文件、目录、日志、统计信息是否正确产生。以acl_queue_unittest.cpp中的MsprofRegisterCallbackTest为例用例不仅调用AclTdtQueueProfCtrlHandle还通过EXPECT_CALL(MockFunctionTest::aclStubInstance(), MsprofRegTypeInfo(_, _, _))验证回调注册是否真正触达底层 mock见 acl_queue_unittest.cpp。三、如何校验做完整校验避免重复校验3.1 做完整校验UT 用例应根据设计对调用结果做完整校验常见校验点包括返回值或错误码是否准确出参是否被正确填写如acltdtSetQueueAttr设置 name 后出参结构体中的attr.name应与传入值一致被测对象状态是否按预期变化mock 是否以正确参数被调用以及调用次数是否符合预期gmock 的EXPECT_CALL、WillOnce等失败路径上的清理逻辑是否执行。一个常见问题是只校验返回码不校验副作用。这类用例很难防住行为回归应避免。例如acltdtSetQueueAttr的用例中除了断言ret ACL_SUCCESS还进一步比较attr.name与原始字符串是否相等见 acl_queue_unittest.cpp这就是典型的返回值 副作用双重校验。3.2 避免重复校验同一类校验尽量只在一个最贴近场景的用例里完成。重复校验过多会让后续改动引发大量无效失败降低用例可维护性。这与 DT 总纲中一个用例只校验一个明确场景见 DT用例开发总纲是同一原则每个用例聚焦一个场景场景与校验一一对应。四、Runtime 仓常见注意事项4.1 mock 与全局状态必须在 TearDown 中收口Runtime 仓大量用例依赖 gmock 或 mockcpp。无论使用哪一种框架都需要在测试结束时完成校验和清理避免污染后续用例。gmock 模式以 ACL TDT Queue 测试为例class UTEST_QUEUE : public testing::Test { public: UTEST_QUEUE() {} protected: void SetUp() override { MockFunctionTest::aclStubInstance().ResetToDefaultMock(); } void TearDown() override { Mock::VerifyAndClear((void*)(MockFunctionTest::aclStubInstance())); } };这是 acl_queue_unittest.cpp 中的真实写法SetUp中将公共桩MockFunctionTest恢复到默认 mock 行为TearDown中通过Mock::VerifyAndClear校验并清除 mock 期望确保 mock 状态不泄漏到下一个用例。mockcpp 模式class PackageProcessConfigTest : public testing::Test { protected: void TearDown() override { GlobalMockObject::verify(); } };GlobalMockObject::verify()是 mockcpp 的统一收口方式在仓内大量使用例如 tests/ut/adump/adump_base/testcase/dump_manager/dump_manager_utest.cpp 等 adump 用例。如果测试过程中修改了芯片类型、device、环境变量、静态标志位或单例内部状态也必须在TearDown/TearDownTestCase中恢复。例如 runtime 平台相关用例中调用SetChipType后需要把全局芯片类型恢复到测试前状态具体实现可参考 rt_utest_api.cc 等平台目录下的 fixture。4.2 谨慎访问私有成员仓内现有代码中存在#define private public/#define protected public的做法例如 acl_queue_unittest.cpp 中先#define private public再#undef但这只能作为受限场景下的补充手段不应成为默认方案。建议优先顺序如下优先校验公开接口暴露出来的行为若必须观察内部状态优先复用现有 helper、stub 或 accessor例如tests/depends/acl_stub.h中提供的公共桩能力只有在确实没有更好办法时才临时使用#define private public。4.3 文件系统场景要保证隔离和清理很多 Runtime 测试会读写/tmp、相对路径目录或临时文件。新增此类用例时路径命名应带上模块或用例特征避免与其他用例冲突测试完成后要清理临时文件和目录不要依赖其他用例预先创建目录或文件。这条约束在 UT代码规范 中被固化成了硬性规则临时文件和目录必须有清理逻辑路径命名带模块或用例特征。4.4 兼容性变更要补对应测试如果修改了 ACL 对外结构体、枚举、常量、接口签名或 ABI 相关内容应同步检查是否需要补充或更新兼容性测试。Runtime 仓的兼容性测试集中在tests/ut/acl/testcase/compatibility/下包括struct_check.cpp通过OFFSET_OF_MEMBER校验结构体成员偏移量与sizeof例如断言aclrtUtilizationInfo各成员偏移分别为 0/4/8/12、aclrtBinaryLoadOption的成员偏移等防止结构体布局因改动而破坏 ABIenum_check.cpp校验枚举取值const_check.cpp校验对外常量cast_to_other_check.cpp校验类型转换兼容性。这些用例直接校验对外 ABI 布局是接口变更时最容易无声破坏的部分因此修改对外结构体、枚举、常量、接口签名时务必同步检查该目录及对应模块已有的 ABI/接口回归用例。五、不推荐的 UT 设计以下几类用例需要谨慎应尽量避免只验证调用成功/失败不验证任何结果——无法防住行为回归在一个用例里串多个弱相关场景——问题定位和维护成本高为了覆盖率而硬测不真实的异常组合——制造为覆盖率而覆盖率的伪用例用例依赖前一个用例执行后的残留状态——破坏测试隔离性一旦调整执行顺序或并行执行就会随机失败。如果某个场景已经跨越模块边界需要启动模拟器、设备环境或完整流程通常更适合放到 ST。六、与仓库测试工程的实际衔接6.1 用例写在哪里Runtime 仓测试工程位于tests/目录核心结构如下详见 DT用例开发总纲tests - build_ut.sh: 测试构建、执行、覆盖率统计入口 - depends: 公共桩和依赖替身ge/mmpa/profiling/runtime/slog/tdt/toolchain - ut - acl: ACL 接口测试含 testcase/、testcase_c/ - runtime: Runtime 核心与 C 接口测试 - adump: Dump 相关 UT/ST - msprof: Profiling 相关 UT/ST - platform: 平台能力相关 UT/ST - queue_schedule: 队列调度相关 UT/ST - aicpu_sched: AICPU 调度相关 UT/ST - atrace: trace 相关测试 - tsd: TSD 相关测试 - error_manager: 错误管理测试 - mmpa: 平台抽象层测试 - slog: 日志模块测试新增测试前应优先检查 tests/depends/ 中是否已有可复用的公共桩避免重复造轮子模块私有 stub 和测试数据如tests/ut/runtime/runtime_c/stub/、tests/ut/acl/json/则应放在模块内避免污染公共目录。6.2 常用执行命令# 构建并执行全部测试 bash tests/build_ut.sh -u # 构建并执行指定模块 bash tests/build_ut.sh -u runtime bash tests/build_ut.sh -u acl bash tests/build_ut.sh -u msprof # 使能覆盖率 bash tests/build_ut.sh -c # 使能 AddressSanitizer bash tests/build_ut.sh --asan -u runtimetests/build_ut.sh当前支持的常用 target 包括full、acl、runtime、runtime_c、platform、queue_schedule、aicpu_sched、slog、atrace、msprof、adump、tsd、error_manager、mmpa。如果新增测试会创建大量临时文件或目录建议在本地同时跑一遍覆盖率或 sanitizer尽早暴露泄漏和残留状态问题参见 测试框架指南。6.3 新用例文件加入构建系统Runtime 测试工程使用 CMake 构建。新增用例后至少需要检查以下接入点将新文件加入对应模块的CMakeLists.txt例如UT_FILES或add_executable(...)的源文件列表如果新增了测试子目录需要在父级CMakeLists.txt中补充add_subdirectory(...)如果希望通过bash tests/build_ut.sh -u target直接执行新的模块或子模块需要同步更新 tests/build_ut.sh 中的ut_path_map。示例set(UT_FILES acl_queue_unittest.cpp acl_new_feature_unittest.cpp )七、结语把 checklist 变成用例的出厂质检单UT 用例开发的核心可以浓缩为一句话隔离被测对象校验可观察行为收口全局状态。设计阶段对照输入校验、边界值、资源生命周期、全局状态、平台分支、回调副作用这份 checklist 逐项确认实现阶段坚持完整校验、一个用例一个场景、mock 在TearDown中收口、文件系统隔离清理、兼容性变更补 ABI 测试接入阶段完成 CMake 源文件注册和ut_path_map更新。坚持这套方法Runtime 仓的 UT 才能既防住行为回归又保持长期可维护。延伸阅读与本文配套的 DT用例开发总纲用例布局与构建接入、测试框架指南gtest/gmock/mockcpp 与公共桩用法、UT代码规范断言、mock、隔离的硬性规则共同构成了 Runtime 仓 DT 开发的完整体系。【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考