4. 嵌入式单元测试挑战

好,咱们正式开始动手。这一章我带你把 Ceedling 装好,跑通第一个测试项目。说实话,环境搭建这块看着简单,但坑不少。我当年第一次装的时候,光 Ruby 版本就折腾了半小时。咱们一步步来,稳一点。

为什么选 Ceedling?

嵌入式单元测试的工具链不少,Ceedling 算是把「自动化」做到极致的一个。它底层用的是 Unity(测试框架)和 CMock(模拟生成器),上层用 Ruby 做构建管理。说白了,你写一个测试用例,它自动帮你编译、链接、运行、出报告。

我个人习惯把它叫做「嵌入式测试的脚手架」——架子搭好了,你只管往上堆用例就行。

组件 作用 我遇到的坑
Ruby Ceedling 的运行环境 版本低于 2.5 会报 gem 安装失败
Ceedling 测试项目管理工具 记得用 gem 安装,别用 apt
GCC 交叉编译测试代码 ARM 平台要装 arm-none-eabi-gcc
Make 构建系统底层依赖 Ubuntu 默认带了,不用额外装

第一步:安装 Ruby 和依赖

Ubuntu 20.04/22.04 都测试过,下面的命令直接复制执行就行。

sudo apt update
sudo apt install -y ruby-full build-essential
ruby --version
# 输出应该类似:ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
注意: 不要用 sudo apt install ruby 偷懒,那个版本太老。我吃过这个亏——装完 Ceedling 跑测试,报了一堆 gem 依赖错误,排查了半天才发现是 Ruby 版本问题。

第二步:安装 Ceedling

Ruby 装好之后,用 gem 安装 Ceedling 就一行命令:

sudo gem install ceedling
ceedling version
# 正常输出:Ceedling :: x.x.x

如果遇到权限问题,可以加 --user-install 参数,装到用户目录下。我个人习惯用 sudo gem install,省得后面路径配置麻烦。

第三步:创建第一个测试项目

装好了,咱们来建个项目。Ceedling 提供了脚手架命令,一键生成目录结构。

ceedling new my_first_test
cd my_first_test

执行完,你会看到这样的输出:

  create  project.yml
  create  src/
  create  test/
  create  lib/
  create  support/
  create  vendor/ceedling/
  create  vendor/unity/
  create  vendor/cmock/

嗯,到这里环境就搭好了。是不是很快?

目录结构解析

咱们来看看每个目录是干嘛的。我当年第一次看到这个结构,心想「怎么这么多文件夹」?用熟了才发现,每个目录都有它的道理。

Ceedling 项目目录结构 my_first_test/ src/ test/ lib/ support/ 你的源代码 .c/.h 测试用例 test_*.c 第三方库/模拟库 辅助脚本/配置文件 vendor/ ceedling/ (构建引擎) unity/ (测试框架) cmock/ (模拟生成器) 核心工作流 src/ 写代码 → test/ 写用例 → ceedling test:all 自动编译运行 vendor/ 里的框架你基本不用动,Ceedling 自动管理

每个目录的职责

  • src/:放你的源代码。.c 和 .h 都放这里。Ceedling 会自动扫描这个目录下的所有 .c 文件参与编译。
  • test/:放测试用例文件。命名规则是 test_<模块名>.c。比如你要测 led_controller.c,就建 test_led_controller.c。
  • lib/:放第三方库或者你自己写的模拟库。我一般把硬件抽象层(HAL)的模拟实现放这里。
  • support/:放辅助脚本,比如 project.yml 里引用的自定义构建脚本。
  • vendor/:Ceedling 自动管理的依赖。里面有三个子目录:
    • ceedling/:构建引擎本身
    • unity/:测试断言框架
    • cmock/:自动生成 mock 对象的工具
小技巧: 你不需要手动修改 vendor/ 里的任何文件。Ceedling 升级时,直接 ceedling upgrade 就能更新整个 vendor 目录。我见过有人手改 unity 源码,结果升级后全丢了——白忙活。

跑第一个测试

项目建好了,咱们先跑一下默认的测试,看看环境通不通。

ceedling test:all

如果一切正常,你会看到类似这样的输出:

Test 'test_led_controller.c'
-----------------------------
PASSED

-----------------------
OVERALL TEST SUMMARY
-----------------------
TEST COUNT:  3
PASSED:      3
FAILED:      0
IGNORED:     0

看到 PASSED 三个字,说明环境彻底搭好了。

常见报错: 如果遇到 ERROR: Test executable failed to build,八成是 GCC 没装或者版本不对。检查一下 gcc --version,确保是 7.0 以上。我踩过的一个坑是装了 arm 交叉编译器但没装本地 GCC,结果 Ceedling 找不到 x86 的编译器。

project.yml 配置要点

项目根目录下的 project.yml 是 Ceedling 的配置文件。咱们先不改它,但有几个关键字段你得知道:

配置项 作用 默认值
:project:build_root 编译输出目录 build/
:paths:source 源代码搜索路径 src/**
:paths:test 测试用例搜索路径 test/**
:cmock:mock_path 自动生成的 mock 文件存放位置 build/cmock/
:tools:test_compiler:executable 测试用的编译器 gcc

这些配置在后面的章节会频繁用到。尤其是 :tools:test_compiler,做交叉编译测试时得改成 arm-none-eabi-gcc。

本章小结

咱们这一章干了三件事:装 Ruby 和 Ceedling、创建第一个测试项目、搞懂目录结构。你现在应该能跑通 ceedling test:all 了。如果卡在哪一步,回头检查 Ruby 版本和 GCC 安装——90% 的问题出在这两个地方。