主流框架巡礼:Google Test、Unity/CMock、CppUTest、pytest-embedded、Robot Framework 的优缺点对比

做嵌入式测试这些年,我接触过的测试框架少说也有七八个。每个框架都有自己的脾气,选对了事半功倍,选错了……嗯,我见过团队花三个月搭起来的测试环境,最后因为框架跟硬件耦合太紧,全部推倒重来。

这一章咱们就挨个看看,市面上主流的嵌入式测试框架到底长什么样。我不会只念官方文档,更多是结合我踩过的坑,给你一些实在的参考。

Google Test(GTest)—— C++ 项目的标配

Google Test 在 C++ 圈子里几乎是事实标准。我最早接触它是在一个车载娱乐系统项目里,代码量二十万行,全是 C++11。当时团队选型,几乎没怎么争论就定了 GTest。

优点:

  • 断言丰富:从 EXPECT_EQ 到 ASSERT_DEATH,覆盖了你能想到的所有场景
  • 测试固件(Test Fixture):SetUp/TearDown 机制非常成熟,适合做资源初始化和清理
  • 参数化测试:用 TEST_P 配合 INSTANTIATE_TEST_SUITE_P,一组测试用例跑遍所有边界值
  • 死亡测试:专门验证 assert 和 abort 行为,这在嵌入式安全关键代码里特别有用
  • 社区活跃:遇到问题 StackOverflow 一搜一大把,文档也写得清楚

缺点:

  • 对 C 支持一般:虽然能测 C 代码,但需要 extern "C" 包裹,用起来不够自然
  • 资源占用大:编译出来的测试二进制动辄几 MB,在资源受限的 MCU 上跑不动
  • 没有 Mock 内置:GTest 本身不带 Mock 功能,需要搭配 Google Mock(现在已合并)
  • 交叉编译配置繁琐:我曾在 ARM Cortex-A 上折腾了一周才把 GTest 的 CMake 交叉编译跑通
我的建议:如果你的项目是 C++ 为主,跑在 Linux 或 RTOS 上,内存大于 1MB,GTest 是第一选择。别犹豫。

Unity / CMock —— 资源受限 MCU 的救星

Unity 是我在 STM32 裸机项目里用最多的框架。它和 CMock 是一对好搭档,专门为 C 语言和嵌入式环境设计。

Unity 核心特点:

  • 纯 C 实现,零依赖,编译出来只有几十 KB
  • 测试用例用 TEST_ASSERT_EQUAL 系列宏,语法简洁
  • 支持分组测试(TEST_GROUP / TEST_SETUP / TEST_TEARDOWN)
  • 可以生成 XML 输出,方便 CI 集成

CMock 核心特点:

  • 自动生成 Mock 函数,你只需要写一个 .yml 配置文件
  • 支持 expect 和 return 行为定义
  • 对函数指针、回调、结构体参数都有不错的支持

缺点:

  • 断言种类比 GTest 少,复杂比较需要自己写辅助函数
  • CMock 生成的代码可读性差,调试起来有点痛苦
  • 不支持 C++,纯 C 项目专用
  • 社区规模小,遇到冷门问题可能找不到答案
避坑指南:我曾经在一个项目中直接用 Unity 测硬件寄存器读写,结果测试用例跑一次烧一次 Flash。后来才意识到,Unity 适合测逻辑层,硬件抽象层要用模拟器或 Mock。

CppUTest —— 嵌入式 C++ 的轻量选择

CppUTest 是 GTest 的轻量替代品,专门为嵌入式场景优化。它和 CppUMock 配合使用,在资源有限的 C++ 项目里表现不错。

优点:

  • 编译后体积小,适合 ARM Cortex-M 系列
  • 内置 Mock 支持(CppUMock),不需要额外引入框架
  • 支持 C 和 C++ 混合测试
  • 内存泄漏检测是亮点,我靠它抓出过一个隐藏了两周的堆溢出 bug

缺点:

  • 断言宏命名风格偏老,比如 CHECK 而不是 EXPECT_EQ
  • 参数化测试不如 GTest 灵活
  • 文档质量一般,有些功能要靠读源码才能搞明白
特性 Google Test Unity/CMock CppUTest
语言支持 C++(C 需包裹) 纯 C C / C++
Mock 支持 需 Google Mock CMock 自动生成 CppUMock 内置
编译体积 较大(>1MB) 极小(<100KB) 较小(<500KB)
适用平台 Linux / RTOS 裸机 / MCU MCU / RTOS
社区活跃度 极高 中等 较低

pytest-embedded —— Python 生态的嵌入式测试利器

pytest-embedded 是乐鑫(Espressif)开源的一个框架,专门用来测试嵌入式硬件。说白了,它让你用 Python 写测试用例,然后通过串口或 JTAG 跟目标板通信。

优点:

  • Python 语法简洁,团队上手快
  • 天然支持 pytest 生态,fixture、parametrize、插件全都能用
  • 内置串口监控、DUT 控制、固件烧录功能
  • 支持多 DUT 并行测试,适合产线场景

缺点:

  • 依赖 Python 环境,目标板需要串口或网络连接
  • 不适合纯单元测试,更偏向集成测试和系统测试
  • 对非 ESP 芯片的支持需要自己适配底层通信层

我的经验:pytest-embedded 最适合做硬件在环(HIL)测试。我曾在量产项目中用它写了一套自动化测试脚本,每天凌晨跑 200 个用例,覆盖 12 块开发板,连续跑了三个月没出过问题。

Robot Framework —— 关键字驱动的全能选手

Robot Framework 不是嵌入式专用框架,但它通过串口库和 SSH 库,也能在嵌入式测试里占一席之地。

优点:

  • 关键字驱动,测试用例可读性极高,非技术人员也能看懂
  • 丰富的标准库和第三方库(SerialLibrary、SSHLibrary)
  • 支持数据驱动、行为驱动(BDD)
  • 报告和日志非常漂亮,适合给客户演示

缺点:

  • 执行速度慢,Python 底层 + 关键字解析有性能开销
  • 调试困难,关键字失败时堆栈信息不够直观
  • 不适合做细粒度的单元测试,更适合系统级验证
  • 维护成本高,关键字多了以后,库之间的依赖关系容易乱

框架选型决策流程

说了这么多,到底怎么选?我一般按下面这个流程走:

  1. 先看语言:纯 C 项目优先 Unity/CMock,C++ 项目优先 GTest 或 CppUTest
  2. 再看平台:资源受限的 MCU 选 Unity/CppUTest,Linux 或高性能 RTOS 选 GTest
  3. 然后看测试类型:单元测试用前三个,集成/系统测试用 pytest-embedded 或 Robot Framework
  4. 最后看团队:团队 Python 熟练就上 pytest-embedded,有 QA 非技术人员就上 Robot Framework
嵌入式测试框架选型决策流程 开始选型 项目语言:C 还是 C++? C 项目 → Unity/CMock C++ 项目 → GTest/CppUTest MCU 裸机 → Unity Linux/RTOS → GTest 单元测试:Unity/CMock 单元测试:GTest + Google Mock 系统测试 pytest-embedded Robot Framework

小结

框架没有绝对的好坏,只有合不合适。我见过有人用 GTest 在 64KB 的 MCU 上硬跑,结果 Flash 爆了;也见过有人用 Unity 测 Linux 应用层,Mock 写到怀疑人生。选框架之前,先想清楚你的测试目标是什么——是测逻辑、测接口、还是测硬件?想清楚了,选型就简单了。