今年夏天,我开发了一个用纯c语言编写的嵌入式系统。这是我所在公司接管的一个现有项目。我已经非常习惯使用JUnit在Java中编写单元测试,但不知道为现有代码(需要重构)和添加到系统中的新代码编写单元测试的最佳方法是什么。
有什么项目可以让单元测试纯C代码像使用JUnit测试Java代码一样简单吗?任何特别适用于嵌入式开发(交叉编译到arm-linux平台)的见解都将非常感谢。
今年夏天,我开发了一个用纯c语言编写的嵌入式系统。这是我所在公司接管的一个现有项目。我已经非常习惯使用JUnit在Java中编写单元测试,但不知道为现有代码(需要重构)和添加到系统中的新代码编写单元测试的最佳方法是什么。
有什么项目可以让单元测试纯C代码像使用JUnit测试Java代码一样简单吗?任何特别适用于嵌入式开发(交叉编译到arm-linux平台)的见解都将非常感谢。
当前回答
我编写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有效。
其他回答
在开始寻找模拟函数的方法之前,我还没有深入测试遗留的C应用程序。我非常需要mock来将我想测试的C文件与其他C文件隔离开来。我试过cmock,我想我会采用它。
Cmock扫描头文件,并根据它找到的原型生成模拟函数。mock将允许您在完全隔离的情况下测试C文件。您所要做的就是将您的测试文件链接到模拟对象,而不是真正的对象文件。
cmock的另一个优点是,它将验证传递给模拟函数的参数,并允许您指定模拟函数应该提供的返回值。这对于在函数中测试不同的执行流非常有用。
测试由典型的testA()、testB()函数组成,您可以在其中构建期望、调用函数来测试和检查断言。
最后一步是为unity的测试生成一个运行器。Cmock绑定到统一测试框架。Unity和其他单元测试框架一样容易学习。
很值得一试,而且很容易掌握:
http://sourceforge.net/apps/trac/cmock/wiki
更新1
我正在研究的另一个框架是cmock。
http://code.google.com/p/cmockery/
它是一个支持单元测试和模拟的纯C框架。它不依赖于ruby(与Cmock相反),也很少依赖于外部库。
它需要更多的手工工作来设置模拟,因为它不生成代码。这并不代表现有项目的大量工作,因为原型不会有太大的变化:一旦有了mock,就暂时不需要更改它们(这是我的例子)。额外的类型提供了对模拟的完全控制。如果有什么你不喜欢的,你只需改变你的mock。
不需要特别的测试人员。您只需要创建一个测试数组,并将其传递给run_tests函数。这里也有更多的手工工作,但我绝对喜欢自包含自治框架的想法。
此外,它还包含了一些我不知道的漂亮的C技巧。
总的来说,cmock需要对mock有更多的理解才能开始。例子可以帮助你克服这个问题。看起来它可以用更简单的机制来完成这项工作。
Michael Feather的书《有效地使用遗留代码》介绍了很多专门用于C开发期间单元测试的技术。
有一些与依赖注入相关的技术是特定于C语言的,我在其他任何地方都没有见过。
我们编写CHEAT(托管在GitHub上)是为了便于使用和移植。
它没有依赖关系,不需要安装或配置。 只需要一个头文件和一个测试用例。
#include <cheat.h>
CHEAT_TEST(mathematics_still_work,
cheat_assert(2 + 2 == 4);
cheat_assert_not(2 + 2 == 5);
)
测试编译成一个可执行文件,负责运行测试并报告测试结果。
$ gcc -I . tests.c
$ ./a.out
..
---
2 successful of 2 run
SUCCESS
它也有漂亮的颜色。
C语言中的一个单元测试框架是Check;C语言单元测试框架的列表可以在这里找到,并在下面复制。根据运行时具有多少标准库函数,您可以使用其中的一个,也可以不使用。
AceUnit AceUnit (Advanced C and Embedded Unit) bills itself as a comfortable C code unit test framework. It tries to mimick JUnit 4.x and includes reflection-like capabilities. AceUnit can be used in resource constraint environments, e.g. embedded software development, and importantly it runs fine in environments where you cannot include a single standard header file and cannot invoke a single standard C function from the ANSI / ISO C libraries. It also has a Windows port. It does not use forks to trap signals, although the authors have expressed interest in adding such a feature. See the AceUnit homepage. GNU Autounit Much along the same lines as Check, including forking to run unit tests in a separate address space (in fact, the original author of Check borrowed the idea from GNU Autounit). GNU Autounit uses GLib extensively, which means that linking and such need special options, but this may not be a big problem to you, especially if you are already using GTK or GLib. See the GNU Autounit homepage. cUnit Also uses GLib, but does not fork to protect the address space of unit tests. CUnit Standard C, with plans for a Win32 GUI implementation. Does not currently fork or otherwise protect the address space of unit tests. In early development. See the CUnit homepage. CuTest A simple framework with just one .c and one .h file that you drop into your source tree. See the CuTest homepage. CppUnit The premier unit testing framework for C++; you can also use it to test C code. It is stable, actively developed, and has a GUI interface. The primary reasons not to use CppUnit for C are first that it is quite big, and second you have to write your tests in C++, which means you need a C++ compiler. If these don’t sound like concerns, it is definitely worth considering, along with other C++ unit testing frameworks. See the CppUnit homepage. embUnit embUnit (Embedded Unit) is another unit test framework for embedded systems. This one appears to be superseded by AceUnit. Embedded Unit homepage. MinUnit A minimal set of macros and that’s it! The point is to show how easy it is to unit test your code. See the MinUnit homepage. CUnit for Mr. Ando A CUnit implementation that is fairly new, and apparently still in early development. See the CUnit for Mr. Ando homepage. This list was last updated in March 2008.
更多的框架:
CMocka
CMocka是一个支持模拟对象的C语言测试框架。它易于使用和设置。
请参阅CMocka主页。
标准
Criterion是一个跨平台的C单元测试框架,支持自动测试注册、参数化测试和理论,可以输出多种格式,包括TAP和JUnit XML。每个测试都在自己的进程中运行,因此如果需要,可以报告或测试信号和崩溃。
更多信息请参阅Criterion主页。
HWUT
HWUT是一个通用的单元测试工具,支持c语言。它可以帮助创建makefile,生成大量的测试用例,在最小的“迭代表”中编码,运行状态机,生成c语言存根等等。一般的方法是非常独特的:裁决是基于“好标准输出/坏标准输出”。不过,比较函数是灵活的。因此,任何类型的脚本都可以用于检查。它可以应用于任何可以产生标准输出的语言。
请参阅武汉理工大学主页。
CGreen
一个现代的、可移植的、跨语言的C和c++单元测试和模拟框架。它提供了可选的BDD表示法、模拟库和在单个进程中运行它的能力(使调试更容易)。一个自动发现测试函数的测试运行器是可用的。但是您可以通过编程方式创建自己的。
所有这些特性(以及更多)在CGreen手册中都有解释。
维基百科在单元测试框架列表下给出了C单元测试框架的详细列表:C
首先,看看这里:http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C
我的公司有一个客户使用的C库。我们使用CxxTest(一个c++单元测试库)来测试代码。CppUnit也可以工作。如果你被C卡住了,我推荐RCUNIT(但CUnit也很好)。