news 2026/9/18 18:16:10

CANN Runtime 测试框架指南:基于 gtest / gmock / mockcpp 的 DT 用例开发实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CANN Runtime 测试框架指南:基于 gtest / gmock / mockcpp 的 DT 用例开发实战

CANN Runtime 测试框架指南:基于 gtest / gmock / mockcpp 的 DT 用例开发实战

【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime

本篇指南与 Runtime DT用例开发总纲 配套,聚焦 CANN / runtime 开源仓库中 UT/ST 用例的工程化组织方式。文中将系统梳理 Runtime 仓的测试技术栈(gtest 基类、gmock 与 mockcpp 打桩、公共桩与模块内测试资产、模拟器辅助能力、CMake 构建接入、覆盖率与 Sanitizer 统一入口),并结合仓库源码与脚本给出可落地的实操指引。读完本文,你将知道新增一个测试用例时"该复用哪些现成设施、代码放哪里、如何接入构建、如何跑覆盖率与内存检查",避免重复造轮子。

一、Runtime 仓测试技术栈总览

Runtime 仓测试主要基于gtest(Google Test)搭建用例框架,并在此基础上组合使用以下能力:

能力定位典型用途
testing::Test基类用例生命周期管理SetUp/TearDown中完成公共初始化与清理
gmock已有 mock 类的期望校验EXPECT_CALL(...)校验调用次数与参数
mockcpp全局函数/静态函数/成员函数替换打桩dlopen、driver、runtime 等系统或内部接口
公共桩(tests/depends/跨模块复用依赖替身ge、mmpa、profiling、runtime、slog、tdt、toolchain 桩
模块内stub/data/json/模块私有测试资产仅服务单一模块的桩与场景数据
模拟器与数据管理 helperST/UT 场景辅助SimulatorMgr()创建/销毁平台模拟器、DataMgr()管理场景数据
tests/build_ut.sh统一构建/执行/统计入口覆盖率、AddressSanitizer、按 target 构建执行

编写新用例前,应优先对照上表检查仓库内是否已有可复用的设施。本文后续各节将逐一展开。

二、测试基类:继承testing::Test组织公共初始化

绝大多数用例直接继承testing::Test,并在SetUp/TearDown中完成公共初始化与清理。基类常见职责包括:

  • 恢复默认 mock 行为(防止用例间 mock 残留互相污染);
  • 创建和销毁模拟器;
  • 设置和恢复全局芯片类型、device、环境变量;
  • 校验并清理 mock 对象(如Mock::VerifyAndClear(...)/GlobalMockObject::verify())。

如果多个用例共享同一套初始化逻辑,应抽出统一 fixture,避免重复代码。仓库中也有通过testing::Environment做进程级全局初始化的实践,例如 tests/ut/runtime/runtime/test/main.cc 定义了RtEnvironment

class RtEnvironment : public testing::Environment { public: virtual void SetUp() { MOCKER(drvMemAddressTranslate).stubs().will(returnValue(DRV_ERROR_INVALID_VALUE)); rtSetDevice(0); GlobalMockObject::verify(); std::cout << "Runtime UT Environment SetUP" << std::endl; } virtual void TearDown() { ut::ResetPrimaryDeviceIfActive(); std::cout << "Runtime UT Environment TearDown" << std::endl; } };

该示例展示了基类职责的几个典型动作:先用 mockcpp 恢复/设置默认桩行为,再做设备初始化,随后立即GlobalMockObject::verify()校验,最后在TearDown中复位全局 device 状态。这种"设置 → 使用 → 校验 → 复位"的闭环,正是编写 fixture 时推荐的模式。

三、mock 框架:gmock 与 mockcpp 的选型与用法

3.1 gmock:面向已有 mock 类的期望校验

gmock 适用于已有 mock 类或接口的期望校验场景,常见用法包括:

  • EXPECT_CALL(...):声明对某个 mock 方法的调用期望(次数、参数、返回值行为);
  • Mock::VerifyAndClear(...):校验期望是否全部满足,并清除已设置的行为。

典型场景包括 ACL 相关接口测试,以及需要验证某个 mock 对象被调用次数和参数的场景。gmock 擅长"对象方法级"的交互验证,适合被测对象依赖注入 mock 实例的架构。

3.2 mockcpp:全局函数、静态函数与成员函数替换

mockcpp 适用于全局函数、静态函数、成员函数替换场景,在 Runtime 仓内使用非常普遍。常见接口包括:

  • MOCKER(func):替换普通全局/静态函数;
  • MOCKER_CPP(...):替换 C++ 成员函数/重载函数;
  • MOCKER_CPP_VIRTUAL(...):替换虚成员函数;
  • GlobalMockObject::verify():统一校验所有全局 mock 桩是否按预期被调用。

典型场景:

  • 打桩dlopen/dlsym/access等系统接口,隔离对真实文件系统和动态链接的依赖;
  • 打桩 driver、runtime、device 相关函数,将上层逻辑与硬件驱动解耦;
  • 替换单例内部调用链,隔离被测类对全局状态的依赖。

MOCKER(...)的典型写法为"打桩目标 +.stubs()+.will(...)"三段式,可配合returnValue(...)invoke(...)等行为设置。在 tests/ut/runtime/runtime/test/main.cc 中即可看到MOCKER(drvMemAddressTranslate).stubs().will(returnValue(DRV_ERROR_INVALID_VALUE))的直接使用。

3.3 选型建议

场景推荐框架
类方法调用次数与参数校验gmock(EXPECT_CALL
打桩系统接口(dlopen/dlsym/accessmockcpp(MOCKER
打桩 driver/runtime/device 函数mockcpp(MOCKER
替换单例内部调用链mockcpp(MOCKER_CPP/MOCKER_CPP_VIRTUAL
全局桩统一校验GlobalMockObject::verify()

四、公共桩与测试资产的组织策略

4.1tests/depends/:跨模块复用的公共桩

tests/depends 提供跨模块复用的公共桩,新增测试前应优先检查这里是否已有可复用能力。当前主要包含:

目录桩内容对应源码
tests/depends/ge/依赖组件(GE)相关桩ge_stub.cpp
tests/depends/mmpa/平台抽象层桩mmpa_stub.cpp
tests/depends/profiling/profiling 相关桩profiling_stub.cpp
tests/depends/runtime/runtime/drv 接口桩runtime_stub.cpp
tests/depends/slog/日志桩(含日志捕获能力)slog_stub.cpp
tests/depends/tdt/数据传输相关桩tdt_stub.cpp
tests/depends/toolchain/工具链相关桩toolchain_stub.cpp

公共桩目录下还有 acl_stub.h 以及各子目录的CMakeLists.txt,用于在构建时按需链接对应桩。在新增测试前,先搜索这里是否已有目标接口的桩实现,能显著减少重复劳动。

4.2 模块内stub/data/json/:模块私有测试资产

很多模块会在自己的测试目录下维护专用测试资产,例如:

  • tests/ut/msprof/st/stub/:msprof ST 的私有桩,包含drv_stub.cppmmpa_stub.cppslog_stub.cctsd_stub.cppdevdrv_runtime_api_stub.cpp等与 profiling 场景强耦合的替身;
  • tests/ut/msprof/st/data/:msprof 的场景数据(其中 data_manager.h 定义了数据管理辅助类);
  • tests/ut/acl/json/:ACL 测试的 JSON 配置资产,如dumpConfig.jsonprofConfig.jsontestDump1.jsontestExceptionDump_norm.json等;
  • tests/ut/runtime/runtime_c/stub/:Runtime C 接口测试的私有桩。

组织原则:如果某个 stub 或数据只服务于一个模块,应优先放在模块内,避免污染公共目录;只有多个模块需要复用的桩才应提升到tests/depends/

五、模拟器与辅助能力:优先复用现有 helper

部分 ST/UT 会使用模块内现成的模拟器和数据管理能力,例如:

  • SimulatorMgr():创建/销毁平台模拟器,用于隔离不同 SoC/芯片平台场景;
  • DataMgr():初始化和校验场景数据。

这类能力通常已经和模块场景耦合。例如在 msprof 的 ST 测试中,data_manager.h 定义了如下便捷入口:

inline Cann::Dvvp::Test::DataManager& DataMgr() { return Cann::Dvvp::Test::DataManager::GetInstance(); }

也就是说,DataMgr()实际是Cann::Dvvp::Test::DataManager单例的别名封装,通过单例方式统一管理场景数据。新增用例时应优先复用这类现成 helper,不要重复实现一套新的模拟逻辑,否则既增加维护成本,也容易与既有场景行为不一致。

六、构建接入:将新用例接入 CMake 与build_ut.sh

6.1 CMakeLists.txt 接入点

新增测试代码后,通常需要修改对应模块的CMakeLists.txt。常见接入方式包括:

  1. 将新文件加入UT_FILES:在模块CMakeLists.txt中维护的源文件列表里追加新用例文件;
  2. 将新目录加入add_subdirectory(...):如果新增了独立测试子目录,需要在父级CMakeLists.txt注册;
  3. 为新可执行目标补充依赖:为新测试目标补齐所需的 stub、头文件包含路径和链接库。

仓库中 tests/ut/runtime/runtime/CMakeLists.txt 即以add_executable(runtime_utest ...)的方式组织多个测试可执行目标。以UT_FILES方式接入的示例写法如下:

set(UT_FILES "acl_queue_unittest.cpp" "acl_new_feature_unittest.cpp" )

6.2 更新tests/build_ut.sh的 target 映射

如果新增了可通过bash tests/build_ut.sh -u <target>直接执行的模块,还需要同步更新 tests/build_ut.sh 中的ut_path_maput_name_map两个映射表:

  • ut_path_map:target 名 → 构建输出中的测试可执行文件所在目录(用于构建后自动查找并逐个执行);
  • ut_name_map:target 名 → CMake 可执行目标名(用于指定cmake --build --target)。

当前脚本已注册的 target 包括fullaclruntimeruntime_cplatformqs/queue_scheduleaicpusd/aicpu_schedslogatracemsprofadumptsderror_managermmpa,见 tests/build_ut.sh。

6.3 常用执行命令

# 构建并执行全部测试 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 # 使能覆盖率(等价于 -c / --cov) bash tests/build_ut.sh -c # 使能 AddressSanitizer bash tests/build_ut.sh --asan -u runtime

脚本还支持以下实用参数(见 tests/build_ut.sh):

  • -j<N>:构建线程数,默认 8;
  • -v / --verbose:显示详细构建命令;
  • --ut_timeout=<SECONDS>:为每个 UT 可执行文件设置执行超时(默认 0 表示不限制;设置为正数时依赖系统timeout命令,超时退出码 124/137 会被判定为用例超时失败);
  • -t / --target <target>:仅构建并运行指定的 CMake 目标;
  • --cann_3rd_lib_path=<PATH>:指定 CANN 第三方依赖包安装路径,默认./output/third_party

说明:脚本基于 CMake 构建,构建参数(-DENABLE_UT-DENABLE_ASAN-DENABLE_COV等)在 tests/build_ut.sh 的build_rts()中统一拼装;用例执行阶段会在output/report/ut下输出 gtest XML 报告,并以可执行文件为单位逐个运行、遇失败即退出。

七、覆盖率与 Sanitizer:尽早暴露问题

仓内覆盖率与内存检查的统一入口为tests/build_ut.sh

# 覆盖率 bash tests/build_ut.sh -c # AddressSanitizer bash tests/build_ut.sh --asan -u runtime
  • 覆盖率-c / --cov会在ENABLE_COV开启的情况下,用lcov收集并过滤统计信息(过滤/usr/*output/*tests/*、第三方依赖与build/*等路径),最终通过genhtmlcov/目录生成 HTML 覆盖率报告,详见 tests/build_ut.sh;
  • AddressSanitizer--asan会先校验libasan.solibubsan.solibtsan.so是否存在(缺失时会给出apt install libasan6 libubsan1 libtsan2之类的安装提示,并要求库版本与 gcc 版本匹配,例如 gcc 9.5.0 对应libasan6),再通过LD_PRELOAD注入 sanitizer 库后运行用例,见 tests/build_ut.sh。

实践建议:如果新增测试会创建大量临时文件或目录,建议在本地同时跑一遍覆盖率或 sanitizer,尽早暴露内存泄漏、未释放资源和残留状态问题——这类问题只有在全局校验与 sanitizer 组合下才容易被稳定发现。

八、总结与上手清单

Runtime 仓的测试设施已经相当完备,新增用例时建议按以下清单操作:

  1. 复用优先:先检查 tests/depends 公共桩与目标模块内的stub/data/json/目录,确认是否有可直接复用的桩、数据和 helper;
  2. 选对 mock 框架:类方法期望校验用 gmock,系统接口与全局函数打桩用 mockcpp,并遵循MOCKER(...).stubs().will(...)GlobalMockObject::verify()的闭环;
  3. 组织好 fixture:用testing::Test/testing::Environment收敛公共初始化,负责 mock 恢复、模拟器创建销毁、全局状态设置与复位;
  4. 接入构建:更新模块CMakeLists.txtUT_FILES/add_subdirectory/ 目标依赖),如需独立 target 则同步更新 tests/build_ut.sh 的ut_path_maput_name_map
  5. 回归验证:用bash tests/build_ut.sh -u <target>验证用例通过,再结合-c(覆盖率)与--asan(Sanitizer)做一次完整体检。

通过这套流程,新用例可以最大程度复用既有测试设施,保持仓库测试资产的整洁与一致。更完整的用例设计规范(单场景校验、命名规范、全局状态恢复等)可进一步阅读 UT用例开发指导 与 Runtime DT用例开发总纲。

【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 18:15:40

OpenClaw v2.7.9 一键部署完,模型 Base URL 填 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 18:15:29

agent-plugins示例目录教程:valid/invalid测试夹具实战演练

agent-plugins示例目录教程&#xff1a;valid/invalid测试夹具实战演练 【免费下载链接】agent-plugins 项目地址: https://gitcode.com/GitHub_Trending/skills16/agent-plugins agent-plugins 是官方维护的 Flutter/Dart 智能体技能插件集合&#xff0c;其配套的 Ski…

作者头像 李华
网站建设 2026/9/18 18:14:49

VMware共享文件夹三步闭环:Tools驱动+UNC映射+服务验证

简介&#xff1a;本资源是一份面向VMware初学者与虚拟化实践者的实操指南&#xff0c;聚焦解决Windows主机与虚拟机间文件共享这一高频痛点问题。内容以图文结合方式&#xff0c;系统讲解共享文件夹配置全流程&#xff1a;从虚拟机设置中添加主机目录、载入windows.iso安装VMwa…

作者头像 李华
网站建设 2026/9/18 18:12:50

JMeter JSON提取器实战:单值、全值与多参数提取避坑指南

Jmeter 的 JSON 提取器&#xff08;JSON Extractor&#xff09;这个后置处理器&#xff0c;我在几乎每一个需要接口串联的压测脚本和自动化校验脚本里都会用它。它的活儿说穿了很朴素&#xff1a;从上一次请求返回的 JSON 报文里&#xff0c;把某个字段抠出来&#xff0c;存成 …

作者头像 李华
网站建设 2026/9/18 18:11:00

OpenOcta 同时挂 MCP 和 Agent Skills,模型调用走 TaoToken 统一接入

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 18:10:27

离散信号描述与典型序列:δ(n)、u(n)与周期判定

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华