使用Check框架测试C语言中调用printf的无返回值void函数
C语言测试仅输出到stdout的void函数方案
核心思路是将标准输出(stdout)临时重定向到内存缓冲区,调用待测函数后恢复标准输出,再比对缓冲区内容与预期值即可实现这类无返回值函数的测试。
具体实现步骤
- 备份原始stdout的流指针,避免重定向后无法恢复正常输出
- 创建关联动态内存缓冲区的内存流,将stdout重定向到该内存流
- 调用待测试的void函数,此时函数内所有
printf输出都会写入内存缓冲区 - 刷新流确保所有输出完全写入缓冲区,恢复原始stdout
- 对比缓冲区内容与预期输出,调用check框架的断言接口做校验
- 测试完成后释放内存缓冲区,避免内存泄漏
代码示例(结合check框架)
首先是待测试的目标函数:
// 待测无返回值输出函数 void print_info(void) { printf("user id: %d\n", 1001); printf("user role: admin\n"); }
对应的check单元测试用例:
#include <check.h> #include <stdio.h> #include <stdlib.h> #include <string.h> START_TEST(test_print_info_output) { // 备份原始stdout FILE *old_stdout = stdout; char *output_buf = NULL; size_t buf_len = 0; // 创建内存流并重定向stdout stdout = open_memstream(&output_buf, &buf_len); ck_assert_ptr_ne(stdout, NULL); // 调用待测函数 print_info(); // 刷新流并恢复stdout fflush(stdout); fclose(stdout); stdout = old_stdout; // 校验输出是否符合预期 const char *expected = "user id: 1001\nuser role: admin\n"; ck_assert_str_eq(output_buf, expected); // 释放缓冲区内存 free(output_buf); } END_TEST
注意事项
- 上述方案适用于POSIX兼容系统(Linux、macOS等),Windows环境可通过
CreatePipe结合文件描述符替换实现相同逻辑,核心思路一致 - 必须在测试逻辑结束后立刻恢复stdout,否则后续测试日志、程序输出都会写入缓冲区,导致控制台无正常输出
- 若待测函数输出包含动态内容(如时间戳、随机值),可先对缓冲区内容做正则匹配或局部校验,不需要完全匹配整段字符串
- 若编译环境不支持
open_memstream,可改用管道实现:创建管道后将stdout的文件描述符替换为管道写端,从管道读端读取输出内容到缓冲区即可
内容的提问来源于stack exchange,提问作者Funny
相关产品推荐
相关产品推荐

