news 2026/4/18 14:27:50

简单理解:什么是CMocka ?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
简单理解:什么是CMocka ?

CMocka 是一款面向 C 语言的轻量级单元测试框架,核心支持Mock 对象模拟,特别适合嵌入式 / SOC 开发中的代码测试。

核心定位

它是从谷歌的 Cmockery 框架继承而来的工具,主打 **“仅依赖标准 C 库”**,能在 Linux、Windows、嵌入式等多平台运行,解决 C 代码(尤其是硬件依赖型代码)的 “单元测试难落地” 问题。

关键功能

  1. Mock 对象模拟可以为依赖的硬件驱动、外部模块创建 “替身函数”:

    • 预设函数的返回值 / 输出参数(比如模拟uart_send()的成功返回,无需真实串口硬件);
    • 校验函数的调用次数、入参、调用顺序(比如确认sensor_read()是否被正确调用)。
  2. 基础测试能力

    • 提供丰富的断言宏(如assert_int_equal验证数值相等);
    • 支持测试夹具(Setup/Teardown),统一管理测试的初始化 / 清理;
    • 检测内存泄漏、缓冲区溢出等问题。
  3. 适配嵌入式场景

    • 仅依赖标准 C 库,可通过交叉编译适配嵌入式平台;
    • 不使用fork()等系统调用,适合资源受限的硬件环境。

典型用法(示例)

比如测试一个依赖 UART 的函数:

#include <cmocka.h> #include "uart.h" // 被依赖的模块 // 被测试函数:调用uart_send发送错误码 void report_error(int code) { uart_send(code); } // Mock替身函数(CMocka自动生成或手动定义) void uart_send(int code) { check_expected(code); // 校验入参是否符合预期 } // 测试用例 void test_report_error(void **state) { (void)state; expect_value(uart_send, code, 100); // 预设期望入参是100 report_error(100); // 执行被测试函数 } // 运行测试 int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_report_error), }; return cmocka_run_group_tests(tests, NULL, NULL); }

优势

  • 轻量无依赖,易集成到嵌入式项目;
  • 同时支持单元测试和接口测试;
  • 输出格式灵活(支持 TAP、JUnit XML,适配持续集成)。

一、环境准备(核心依赖)

CMocka 仅依赖:

  1. C 编译器(gcc/clang/arm-none-eabi-gcc)
  2. 构建工具(cmake 3.10+ 或 make)
  3. CMocka 源码(推荐稳定版 1.1.5)
步骤 1:下载 CMocka 源码
# 方式1:直接下载源码包(推荐) wget https://cmocka.org/files/1.1/cmocka-1.1.5.tar.xz tar -xvf cmocka-1.1.5.tar.xz # 方式2:git克隆(最新版) git clone https://git.cryptomilk.org/projects/cmocka.git

二、编译集成(分 2 种场景)

场景 1:Linux 主机测试(x86/x64,最快验证)
# 1. 进入源码目录,创建编译目录 cd cmocka-1.1.5 mkdir build && cd build # 2. cmake配置(指定安装路径,避免污染系统) cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/cmocka \ -DCMAKE_BUILD_TYPE=Release \ -DUNIT_TESTING=OFF # 关闭CMocka自身的单元测试 # 3. 编译+安装 make -j4 sudo make install
场景 2:嵌入式交叉编译(如 ARM Cortex-M)
# 1. 定义交叉编译工具链(替换为你的工具链路径) export CROSS_COMPILE=arm-none-eabi- export CC=${CROSS_COMPILE}gcc export AR=${CROSS_COMPILE}ar export STRIP=${CROSS_COMPILE}strip # 2. cmake配置(核心:指定交叉编译) cmake .. -DCMAKE_INSTALL_PREFIX=/your/project/cmocka-arm \ -DCMAKE_BUILD_TYPE=Release \ -DUNIT_TESTING=OFF \ -DCMAKE_SYSTEM_NAME=Generic \ # 无操作系统(裸机) -DCMAKE_C_FLAGS="-mthumb -mcpu=cortex-m4" # 适配你的MCU架构 # 3. 编译+安装到项目目录 make -j4 make install
关键说明:
  • 安装后会生成:
    • 头文件:include/cmocka.h
    • 库文件:lib/libcmocka.a(静态库,嵌入式优先用)

三、项目集成(3 步接入你的代码)

假设你的嵌入式项目结构如下:

your_project/ ├── src/ # 业务代码(如norflash_test.c) ├── test/ # 测试代码 ├── cmocka/ # 存放CMocka的头文件+库文件 └── CMakeLists.txt
步骤 1:复制 CMocka 文件到项目
# 复制头文件 cp /usr/local/cmocka/include/cmocka.h your_project/cmocka/ # 复制静态库(主机/嵌入式对应不同库) # 主机: cp /usr/local/cmocka/lib/libcmocka.a your_project/cmocka/ # 嵌入式: cp /your/project/cmocka-arm/lib/libcmocka.a your_project/cmocka/
步骤 2:编写 CMakeLists.txt(核心)
cmake_minimum_required(VERSION 3.10) project(embedded_test) # 1. 引入CMocka include_directories(${PROJECT_SOURCE_DIR}/cmocka) # 头文件路径 link_directories(${PROJECT_SOURCE_DIR}/cmocka) # 库文件路径 # 2. 要测试的业务代码(如norflash驱动) add_library(business_code STATIC src/norflash.c) # 3. 测试代码(如test_norflash.c) add_executable(norflash_test test/test_norflash.c) # 链接CMocka和业务代码 target_link_libraries(norflash_test business_code cmocka) # 嵌入式额外配置(根据你的MCU调整) if(ARM_EMBEDDED) set(CMAKE_C_FLAGS "-mthumb -mcpu=cortex-m4 -ffreestanding -nostdlib") # 链接脚本、启动文件等 target_link_libraries(norflash_test ${PROJECT_SOURCE_DIR}/src/link.ld) endif()
步骤 3:编写第一个测试用例(示例:NOR Flash 读写测试)

test/test_norflash.c中:

#include <cmocka.h> #include "norflash.h" // 你的NOR Flash驱动头文件 // 测试夹具:每个用例执行前初始化 static int setup_norflash_test(void **state) { // 模拟NOR Flash初始化(无需真实硬件) norflash_init(); return 0; } // 测试夹具:每个用例执行后清理 static int teardown_norflash_test(void **state) { // 模拟释放资源 norflash_deinit(); return 0; } // 测试用例1:验证NOR Flash读操作 static void test_norflash_read(void **state) { uint8_t buf[4] = {0}; // 调用被测函数:读取地址0x0000的4字节 int ret = norflash_read(0x0000, buf, 4); // 断言:返回值应为0(成功) assert_int_equal(ret, 0); // 断言:读取的数据符合预期(模拟场景可预设) assert_memory_equal(buf, (uint8_t[]){0x11, 0x22, 0x33, 0x44}, 4); } // 测试用例2:验证Mock函数调用(模拟写操作) static void test_norflash_write(void **state) { uint8_t data[] = {0xaa, 0xbb}; // 预设:期望norflash_erase被调用1次,入参为0x1000 expect_value(norflash_erase, addr, 0x1000); expect_call_count(norflash_erase, 1); // 执行被测函数 norflash_write(0x1000, data, 2); // 校验:norflash_erase确实被调用 check_expected_calls(); } // 注册测试用例 int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(test_norflash_read, setup_norflash_test, teardown_norflash_test), cmocka_unit_test(test_norflash_write), }; // 运行所有测试 return cmocka_run_group_tests(tests, NULL, NULL); }

四、运行验证

场景 1:Linux 主机运行
# 编译测试程序 cd your_project mkdir build && cd build cmake .. -DARM_EMBEDDED=OFF make -j4 # 运行测试 ./norflash_test

✅ 成功输出示例:

[==========] Running 2 test(s). [ RUN ] test_norflash_read [ OK ] test_norflash_read [ RUN ] test_norflash_write [ OK ] test_norflash_write [==========] 2 test(s) passed.
场景 2:嵌入式运行(裸机)
# 编译生成bin/hex文件 cmake .. -DARM_EMBEDDED=ON make -j4 # 下载到硬件(用你的烧录工具,如openocd/jlink) openocd -f interface/jlink.cfg -f target/stm32f4x.cfg -c "program norflash_test.hex verify reset exit"

✅ 验证方式:通过串口 / 调试器查看测试输出(需在代码中适配 printf 到串口)。

总结

  1. 核心步骤:下载 CMocka → 编译(主机 / 交叉编译)→ 项目集成(头文件 + 库 + CMake)→ 编写测试用例 → 运行验证;
  2. 嵌入式关键:交叉编译时指定CMAKE_SYSTEM_NAME=Generic和 MCU 架构参数,用静态库libcmocka.a
  3. 简化技巧:新手可先在 Linux 主机完成测试验证,再移植到嵌入式硬件。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 8:42:02

5分钟掌握PHP时间处理神器:TimeHelper核心功能全解析

5分钟掌握PHP时间处理神器&#xff1a;TimeHelper核心功能全解析 【免费下载链接】time-helper 一个简单快捷的PHP日期时间助手类库。 项目地址: https://gitcode.com/zjkal/time-helper zjkal/time-helper是一个简单快捷的PHP日期时间助手类库&#xff0c;它让复杂的时…

作者头像 李华
网站建设 2026/4/18 9:31:41

Miniconda-Python3.9镜像安装PyTorch GPU版完整教程

Miniconda-Python3.9镜像安装PyTorch GPU版完整教程 在如今的AI开发环境中&#xff0c;一个常见的场景是&#xff1a;你刚拿到一台配置了高端NVIDIA显卡的服务器&#xff0c;满心期待地准备开始训练模型&#xff0c;结果却卡在了环境配置上——torch.cuda.is_available() 返回…

作者头像 李华
网站建设 2026/4/18 4:41:35

手把手教你用Miniconda创建独立Python环境运行大模型

手把手教你用Miniconda创建独立Python环境运行大模型 在训练一个大模型时&#xff0c;你是否曾遇到过这样的场景&#xff1a;本地调试一切正常&#xff0c;一到服务器上却报错 ModuleNotFoundError&#xff1f;或者团队成员之间反复争论“为什么我的代码在你那儿跑不通”&#…

作者头像 李华
网站建设 2026/4/17 23:33:15

CL4R1T4S:揭秘AI模型背后的系统指令,让AI透明度触手可及

在人工智能日益普及的今天&#xff0c;你是否曾好奇AI助手为何会以特定的方式回应&#xff1f;为什么不同的AI模型会有截然不同的行为模式&#xff1f;CL4R1T4S项目正是为了解答这些疑问而生&#xff0c;它通过收集和分析各大AI模型的系统提示词&#xff0c;让普通用户也能深入…

作者头像 李华
网站建设 2026/4/18 1:10:23

Anaconda安装后遗症:残留文件清理指南

Anaconda安装后遗症&#xff1a;残留文件清理指南 在数据科学和机器学习开发中&#xff0c;一个干净的 Python 环境往往是实验可复现、部署稳定的第一步。然而&#xff0c;许多开发者都曾经历过这样的场景&#xff1a;明明已经“卸载”了 Anaconda&#xff0c;重新安装 Minico…

作者头像 李华
网站建设 2026/4/18 7:59:11

Crowbar游戏模组制作工具:从入门到精通的终极指南

Crowbar游戏模组制作工具&#xff1a;从入门到精通的终极指南 【免费下载链接】Crowbar Crowbar - GoldSource and Source Engine Modding Tool 项目地址: https://gitcode.com/gh_mirrors/crow/Crowbar 想要为《半条命》、《反恐精英》等经典游戏创建自己的模组&#x…

作者头像 李华