ceedling就是一款嵌入式软件测试框架。ceedling是一个用ruby语言编写的C语言自动化测试框架,它集成了Cmock、Unity和Cexception等多个开源项目。在整个ceedling框架中,使用unity进行代码测试,使用CMock生成模拟函数,使用CException进行异常处理,ceedling本身可以理解为对这三个框架的整合,提供自动化配置、操作等,简化开发。
一 ceedling安装步骤
ceedling使用ruby开发脚本,使用gcc工具链编译,因此需要安装ruby和gcc。
(1)首先安装ruby。ruby安装包见《rubyinstaller-devkit-3.0.2-1-x64.zip》
(2)安装 gcc。拷贝文件夹《mingw64》拷贝到目录C:\Program Files\下。之后把路径C:\Program Files\mingw64\bin添加到系统环境变量中。
验证:gcc --version
(3)安装ceedling,执行命令gem install ceedling,执行此命令需要连接外网。
安装完毕验证:ceedling version
二 ceedling配置
ceedling是通过project.yml来进行配置。project.yml解释如下:
# 项目元数据
:project:
:use_exceptions: FALSE # 是否启用 C++ 异常(C 项目一般 FALSE)
:use_test_preprocessor: TRUE # 是否对测试文件也跑一遍预处理器
:use_auxiliary_dependencies: TRUE
:build_root: build # 所有中间文件、目标文件、测试可执行文件都会放到 build/
:test_file_prefix: test_ # 测试源文件必须 test_ 开头(可改)
# 路径配置
:paths:
:test:
- test/** # 递归搜索 test 目录下所有测试文件
:source:
- src/** # 被测源码
:include:
-
inc # 公共头文件
-
mocks # 手动桩或额外包含路径
-
third_party/cmsis/include # 第三方库
# 工具链定义
:tools:
:test_compiler:
:executable: gcc # 可执行文件名(Windows 用 gcc.exe)
:arguments:
-
-std=c11 # C 语言标准
-
-Wall
-
-Wextra
-
-Werror # 把告警当错误
-
-Wno-unused-parameter # 针对 Unity 生成代码的告警
-
-I"${':include'}" # 展开 :paths:include 里的路径
-
-I"${':source'}"
-
-DUNITY_INCLUDE_CONFIG_H # 告诉 Unity 使用 Ceedling 生成的配置
# 全局宏定义
:defines:
:common: &common_defines # 定义锚点,后面可以引用
-
UNIT_TEST
-
DEBUG=1
:test:
-
*common_defines # 引用锚点
-
TEST # 仅在测试编译时生效
:release:
-
*common_defines
-
NDEBUG # 发布版本去掉 assert
# CMock 配置
:cmock:
:mock_prefix: mock_ # 生成的桩文件名前缀
:when_no_prototypes: :warn # 如果头文件没有函数原型就告警
:enforce_strict_ordering: TRUE # 是否严格要求函数调用顺序
:includes:
-
stddef.h # 每个桩文件都强制包含的头
-
stdint.h
:treat_inlines: :include # 也 mock 声明为 static inline 的函数
:treat_externs: :exclude # 不自动 mock extern 变量
:plugins:
-
:ignore # 支持 ignore_args
-
:callback # 支持 callback 插件
-
:expect_any_args # 支持 ExpectAnyArgs
# Unity 配置
:unity:
:defines:
- UNITY_INCLUDE_DOUBLE # 让 Unity 支持 TEST_ASSERT_EQUAL_DOUBLE
# 插件(gcov / bullseye / xml 报告等)
:plugins:
:enabled:
-
gcov # 覆盖率报告
-
xml_tests_report # 生成 JUnit XML 给 CI
-
stdout_pretty_tests_report # 彩色命令行输出
:gcov:
:reports:
- HtmlDetailed # 生成 html
:gcovr:
:html_medium_threshold: 75 # 覆盖率 75% 以上标绿
:html_high_threshold: 90
# 环境变量
:environment:
-
:path:
-
C:\tools\mingw64\bin # Windows 下额外 PATH
三 如何使用ceedling编写测试代码
- 在某一目录(英文目录)下,执行如下命令:
ceedling new my_project
目录结构自动生成如下所示:
my_project
├─ src/ # 放被测源码
├─ test/ # 放测试文件
├─ project.yml # 配置文件
把你要测试的源文件(例i2c_dw_core.c)拷贝到src/目录下,并且i2c_dw_core.c的头文件导入更换为:
#include "i2c_dw_core.h"
#include "i2c_dw_core_cmock.h"
- 新建文件i2c_dw_core.h,内容如下所示:
#ifndef I2C_DW_CORE_H
#define I2C_DW_CORE_H
#include "base.h"
如下函数声明是待测函数的声明
int i2c_dw_init_master(struct dw_i2c_dev *dev);
void i2c_dw_xfer_msg(struct dw_i2c_dev *dev);
#endif
(3)新建文件i2c_dw_core_cmock.h内容如下所示:
#ifndef I2C_DW_CORE_CMOCK
#define I2C_DW_CORE_CMOCK
如下函数声明是需要打桩的函数的声明
void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev);
void rt_completion_done(struct rt_completion *completion);
#endif
(4)在src/目录下新建文件base.h(所有待测源文件的数据类型定义可以共用base.h),内容如下:
#ifndef BASE_H
#define BASE_H
开始添加待测文件用到的所有数据类型的定义
typedef unsigned int UINT32;
#endif
(5)生成文件test_i2c_dw_core.c,并在此文件中编写测试代码
执行命令ceedling module:create[i2c_dw_core]
在test/目录下,打开文件test_i2c_dw_core.c进行测试代码编写。
首先在#include "i2c_dw_core.h"语句后添加如下一条语句: #include "mock_i2c_dw_core_cmock.h"
开始编写测试代码。。。
四 ceedling常用打桩宏及其用法
一般用前四个
(1)Func_Ignore()
彻底忽略型
Func要求:无返回值,如有返回值则不能使用此宏。有无入参均可。
源文件调用多少次都放行。
(2)Func_IgnoreAndReturn(ret)
忽略入参,但固定返回ret
Func要求:有返回值。有无入参均可。
源文件调用多少次都放行。
(3)Func_Expect(arg1, arg2, ...)
Func要求:无返回值,有入参。
这个宏作用是告诉 CMock "下一次调用 Func 时,实参必须完全等于括号里的值,否则测试立即失败"。参数按位置逐一比较。
此宏只能匹配一次调用(调用后就被"消耗"掉)。
如果函数还有返回值,需用 Func_ExpectAndReturn(arg1, arg2, ..., ret)
(4)Func_ExpectAndReturn(a,b,ret)
Func要求:有返回值,有入参。这个宏作用是期望下一次调用的参数必须严格匹配括号里的值,并且让调用返回ret。参数个数、顺序、值都必须完全一致
此宏只能匹配一次调用(调用后就被"消耗"掉)。
(5)Func_ExpectAnyArgs()
Func要求:无返回值,有入参。
这个宏作用是告诉 CMock"下一次调用 Func 时,不管传什么参数,都算通过"。
只能匹配一次调用(调用后就被"消耗"掉)。
(6)Func_ExpectAnyArgsAndReturn(ret)
Func要求:有返回值,有入参。
这个宏作用是告诉CMock:"下一次调用 Func 时,参数完全无所谓,但必须返回ret"。
此宏只能匹配一次调用(调用后就被"消耗"掉)。
五 执行单元测试用例
以管理员身份打开windows终端,然后进入工程目录my_project
执行如下命令:
ceedling clean
ceedling test:test_i2c_dw_core.c #仅执行测试代码文件test_i2c_dw_core.c
ceedling gcov:test_i2c_dw_core.c #生成测试报告,测试报告在目录my_project\build\artifacts\gcov\gcovr下。