今年夏天,我开发了一个用纯c语言编写的嵌入式系统。这是我所在公司接管的一个现有项目。我已经非常习惯使用JUnit在Java中编写单元测试,但不知道为现有代码(需要重构)和添加到系统中的新代码编写单元测试的最佳方法是什么。

有什么项目可以让单元测试纯C代码像使用JUnit测试Java代码一样简单吗?任何特别适用于嵌入式开发(交叉编译到arm-linux平台)的见解都将非常感谢。


当前回答

C语言有一个优雅的单元测试框架,它支持模拟对象,叫做cmocka。它只需要标准的C库,适用于各种计算平台(包括嵌入式)和不同的编译器。

它还支持不同的消息输出格式,如Subunit、Test Anything Protocol和jUnit XML报告。

cmocka也可以在嵌入式平台上工作,也支持Windows。

一个简单的测试是这样的:

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>

/* A test case that does nothing and succeeds. */
static void null_test_success(void **state) {
    (void) state; /* unused */
}

int main(void) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(null_test_success),
    };
    return cmocka_run_group_tests(tests, NULL, NULL);
}

API有完整的文档,源代码中有几个示例。

要开始使用cmocka,您应该阅读LWN.net上的文章:在C中使用模拟对象进行单元测试

cmocka 1.0已于2015年2月发布。

其他回答

我编写Libcut只是出于对现有C单元测试库的不满。它具有原语的自动类型字符串(不需要test_eq_int, test_eq_long, test_eq_short,等等…)对于原语和字符串只有两个不同的集合),并且由一个头文件组成。这里有一个简短的例子:

#include <libcut.h>

LIBCUT_TEST(test_abc) {
    LIBCUT_TEST_EQ(1, 1);
    LIBCUT_TEST_NE(1, 0);
    LIBCUT_TEST_STREQ("abc", "abc");
    LIBCUT_TEST_STRNE("abc", "def");
}

LIBCUT_MAIN(test_abc);

不过,它只对C11有效。

尝试lcut !- http://code.google.com/p/lcut

作为一个C语言新手,我发现名为“C测试驱动开发”的幻灯片非常有用。基本上,它使用标准assert()和&&来传递消息,没有任何外部依赖。如果有人习惯了全栈测试框架,这可能就不适用了:)

我不使用框架,我只是使用自动工具“检查”目标支持。实现一个“main”并使用assert。

我的测试目录Makefile.am(s)看起来像这样:

check_PROGRAMS = test_oe_amqp

test_oe_amqp_SOURCES = test_oe_amqp.c
test_oe_amqp_LDADD = -L$(top_builddir)/components/common -loecommon
test_oe_amqp_CFLAGS = -I$(top_srcdir)/components/common -static

TESTS = test_oe_amqp

如果你还在寻找测试框架,CUnitWin32是Win32/NT平台的一个。

这解决了我在其他测试框架中遇到的一个基本问题。也就是说,全局/静态变量处于确定性状态,因为每个测试都是作为单独的进程执行的。