Unity单元测试:C语言轻量级框架实战
目录
0.如何编写单元测试用例:
1.工程中建一个Middlewares文件,在这个文件夹里新建一个Unity文件夹,然后移植进keil
2.在Unity文件夹中创建unity_config.h头文件,重定向Unity的字符输出接口函数
3.修改unity_internals.h,开启对unity_config.h的包含
4.在main.c中定义 setUp 和 tearDown两个函数的原型
补充:
MobaXterm的认识
6.实验效果
7.分析
1.TEST_ASSERT_EQUAL_INT
2.开始测试与结束测试API
开源仓库: https://github.com/ThrowTheSwitch/Unity/releases
Unity 是一个用于 C 语言的轻量级单元测试框架。
移植前首先了解如何用
0.如何编写单元测试用例:
首先我们需要知道单元测试的指标有哪些,
1. 正确性
2. 可靠性
3. 性能
4. 断言数量
5. 边界值测试
6. 异常处理
7. 代码耦合度
8.覆盖率
单元测试步骤:
1.测试之前我们需要拿到由软件开发人员所撰写的代码详细设计并了解函数功能
2.通过输入输出信息,在代码中“打桩”,隔绝其余模块信息干扰
3.根据输入信号的范围,设计测试案例,
4.设计的测试案例要能覆盖到所有分支,并验证输出结果是否符合预期
1.工程中建一个Middlewares文件,在这个文件夹里新建一个Unity文件夹,然后移植进keil
2.在Unity文件夹中创建unity_config.h头文件,重定向Unity的字符输出接口函数
#ifndef __UNITY_CONFIG_H__
#define __UNITY_CONFIG_H__#ifdef __cplusplus
extern "C"
{
#endif #include "usart.h"#define UNITY_OUTPUT_CHAR(a) HAL_UART_Transmit(&huart1,(uint8_t[]){(uint8_t)(a)},1,10)#ifdef __cplusplus
}
#endif //__cplusplus
#endif //__UNITY_CONFIG_H__
3.修改unity_internals.h,开启对unity_config.h的包含
4.在main.c中定义 setUp 和 tearDown两个函数的原型
-
setUp 函数在测试开启之前运行,用来测试之前的初始化
-
tearDown函数在测试完成之后运行,用于测试之后的清理
void setUp(void)
{}void tearDown(void)
{}
编写测试函数divide_func:如果b==0,返回-1,否则返回a/b的值
int32_t divide_func(const int a,const int b)
{if(0 == b){return -1;}return a/b;
}
编写测试函数test_func和test_zero_catch
-
test_func设置正确的返回值2进行测试
int32_t divide_func(const int a,const int b)
{if(0 == b){return -1;}return a/b;
}
-
test_zero_catch
void test_zero_catch(void)
{TEST_ASSERT_EQUAL_INT(-2,divide_func(2,0));
}
-
安装MobaXterm软件,创建串口会话,设置串口参数,修改默认的换行LF之前加入回车CR
补充:
MobaXterm的认识
MobaXterm 的功能,只需要记住:这是给 Windows 电脑装了个“万能遥控器”。比如:
-
遥控服务器 就像用电视遥控器换台一样,用它连上公司的 Linux 服务器(用 SSH),输入命令就能查看文件、安装软件,甚至重启机器。
-
传文件像拖U盘 连上服务器后,左边会自动显示服务器文件(类似电脑文件夹),直接把本地文件拖进去就上传了,比微信传文件还简单。
-
同时操控多台机器 比如左边连服务器查日志,右边连路由器调试网络,就像浏览器开多个网页一样方便,不用反复开关窗口。
-
在Windows运行Linux软件 比如让服务器上的 MATLAB 软件界面直接显示在你的 Windows 电脑上(类似远程看电影),不用在本地安装。
-
自带工具箱 内置网络检测工具(类似手机测网速)、文本编辑器(类似记事本但更强大),甚至能写脚本自动干活(比如每天自动备份文件)。
举个实际例子: 你买了台云服务器装 Linux 系统,用 MobaXterm 就能: ① 输入服务器IP一键连接(类似输入网址) ② 输入 top
命令查看 CPU 使用率(类似任务管理器) ③ 左边拖拽上传网站代码文件 ④ 右边开新标签连数据库修改配置 ⑤ 直接运行服务器上的网站测试工具,结果直接弹窗显示
6.实验效果
void test_unity(void)
{UNITY_BEGIN();RUN_TEST(test_func);UNITY_END();
}
void test_unity(void)
{UNITY_BEGIN();RUN_TEST(test_zero_catch);UNITY_END();
}
7.分析
1.TEST_ASSERT_EQUAL_INT
在 Unity 单元测试框架中,TEST_ASSERT_EQUAL_INT
是一个核心的断言宏,用于在单元测试中验证两个整数是否相等,是判断测试用例是否通过的关键工具。
具体含义:
TEST_ASSERT_EQUAL_INT(expected, actual)
的作用是:检查 “实际值(actual)” 是否等于 “预期值(expected)”。
-
如果两者相等,当前测试用例通过;
-
如果两者不相等,测试失败,Unity 会自动输出详细的错误信息(包括预期值、实际值、错误发生的文件和行号),帮助你定位问题。
结合代码举例:
1.在 test_func
中:
TEST_ASSERT_EQUAL_INT(2, divide_func(2,1));
这里的含义是:预期 divide_func(2, 1)
的返回值是 2
(因为 2÷1=2)。实际运行后,divide_func(2,1)
确实返回 2
,所以这个测试用例通过。
2.在 test_zero_catch
中:
TEST_ASSERT_EQUAL_INT(-2, divide_func(2,0));
这里的含义是:预期 divide_func(2, 0)
的返回值是 -2
。但实际运行时,divide_func
中当 b=0
时返回 -1
,所以 “实际值(-1)≠ 预期值(-2)”,这个测试用例失败,Unity 会报错提示差异。
简单说:
TEST_ASSERT_EQUAL_INT
就像单元测试中的 “裁判”,它会对比你期望的结果和代码实际运行的结果,如果一致就 “通过”,不一致就 “判错”,帮助你验证代码逻辑是否符合预期。
2.开始测试与结束测试API
在 Unity 单元测试框架中,UNITY_BEGIN()
和 UNITY_END()
是必须的,它们是整个测试流程的 “启动器” 和 “收尾器”,负责初始化测试环境、管理测试生命周期和生成最终的测试报告。
为什么必须加?
-
UNITY_BEGIN()
:测试开始时调用,作用是初始化 Unity 框架(比如重置测试计数器、配置输出设备、准备测试环境等),为后续的测试执行做准备。如果没有它,测试函数可能无法被正确识别和执行,结果也无法被记录。 -
UNITY_END()
:测试全部执行完毕后调用,作用是结束测试流程(比如统计总测试数、失败数,输出最终的测试报告 “OK” 或 “FAIL” 信息,释放测试资源等)。如果没有它,测试结果不会被完整输出,你无法知道测试到底是全部通过还是有失败。
正确使用方法
这两个宏需要成对出现,且必须包裹所有的 RUN_TEST()
调用(即测试函数的执行)。标准用法如下:
// 测试入口函数(通常命名为test_unity或main)
void test_unity(void)
{UNITY_BEGIN(); // 1. 启动测试框架,初始化环境// 2. 运行所有需要执行的测试函数(用RUN_TEST包裹)RUN_TEST(test_func); // 运行第一个测试RUN_TEST(test_zero_catch); // 运行第二个测试// 可以继续添加更多测试...UNITY_END(); // 3. 结束测试,输出最终报告
}
UNITY_BEGIN()
是 “测试开始的信号”,UNITY_END()
是 “测试结束的信号”,所有测试函数的执行必须放在这两个信号之间,框架才能正确工作。