linux函数单元测试的核心是让被测函数可访问、可隔离、可断言;针对普通非static函数、static函数、c++私有成员函数等场景,分别采用头文件暴露、同文件测试或宏控制、逻辑抽离或友元等方式实现,并通过cmake/makefile自动化集成验证闭环。

一、普通非static函数:头文件暴露 + 独立测试工程
这是最直接的情况。只要函数声明在公开头文件(如 utils.h)中,且定义在对应源文件(utils.c)里,就可以:
- 在测试文件(如 test_utils.cpp)中包含该头文件
- 链接 libutils.a 或直接编译 utils.c 进测试程序
- 用 GTest、CppUTest 或轻量级框架(如 couttast)编写用例并断言
示例(GTest):
TEST(UtilsTest, AddShouldReturnSum) {
EXPECT_EQ(add(2, 3), 5);
EXPECT_EQ(add(-1, 1), 0);
}
二、static函数:同文件测试或宏控制可见性
C语言中 static 函数仅在本编译单元可见,无法跨文件调用。常见可靠做法有两种:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
-
同文件内嵌测试代码:把测试函数(如 test_add_internal())和 add_internal() 放在同一个 .c 文件中,通过预处理条件(如
#ifdef UNIT_TEST)包裹测试入口,避免污染生产构建 -
宏替换解除 static 限制:在测试编译时定义宏,使 static 被替换成空或 extern,例如:
#define static(慎用,需确保只在测试构建中生效)
或更安全的写法:#ifdef UNIT_TEST<br> #define STATIC<br>#else<br> #define STATIC static<br>#endif<br>STATIC int helper_func() { ... }
三、C++类内私有/静态成员函数:测试夹具 + 友元或提取逻辑
对 private 或 static 成员函数,不建议强行暴露。推荐路径是:
- 将核心算法逻辑抽离为独立的自由函数(非成员),再在类中调用——这部分可直接单元测试
- 若必须测私有函数,可在测试类中用
friend class TestMyClass;声明,赋予其访问权限(仅限同一翻译单元) - 使用 GTest 的 Test Fixture 搭配 SetUp/TearDown,构造完整上下文后验证公有接口行为,间接覆盖私有逻辑
四、构建与验证闭环:Makefile/CMake 自动化集成
函数封装后的测试不能停留在手动运行。应通过构建系统保障可重复验证:
- 在 CMakeLists.txt 中用
add_executable(test_xxx)构建测试目标,并链接被测模块 - 用
add_test()注册测试项,配合ctest统一执行 - 结合 gcov/lcov 生成覆盖率报告,确认封装函数是否被真正执行到
- Makefile 中可封装
make test和make coverage目标,隐藏细节,提升团队可用性










