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

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


当前回答

我将CxxTest用于嵌入式c/c++环境(主要是c++)。

我更喜欢CxxTest,因为它有一个perl/python脚本来构建测试运行器。在进行了一些设置之后(因为不需要编写测试运行程序,所以还会更小),它非常容易使用(包括示例和有用的文档)。大部分工作是设置代码访问的“硬件”,这样我就可以有效地进行单元/模块测试。在此之后,很容易添加新的单元测试用例。

如前所述,它是一个C/ c++单元测试框架。所以你需要一个c++编译器。

CxxTest用户指南 CxxTest维基

其他回答

如果你熟悉JUnit,那么我推荐CppUnit。 http://cppunit.sourceforge.net/cppunit-wiki

这是假设你有c++编译器来做单元测试。如果没有,那么我必须同意亚当·罗森菲尔德的观点,支票就是你想要的。

我将CxxTest用于嵌入式c/c++环境(主要是c++)。

我更喜欢CxxTest,因为它有一个perl/python脚本来构建测试运行器。在进行了一些设置之后(因为不需要编写测试运行程序,所以还会更小),它非常容易使用(包括示例和有用的文档)。大部分工作是设置代码访问的“硬件”,这样我就可以有效地进行单元/模块测试。在此之后,很容易添加新的单元测试用例。

如前所述,它是一个C/ c++单元测试框架。所以你需要一个c++编译器。

CxxTest用户指南 CxxTest维基

API完整性检查器- C/ c++库的测试框架:

An automatic generator of basic unit tests for a shared C/C++ library. It is able to generate reasonable (in most, but unfortunately not all, cases) input data for parameters and compose simple ("sanity" or "shallow"-quality) test cases for every function in the API through the analysis of declarations in header files. The quality of generated tests allows to check absence of critical errors in simple use cases. The tool is able to build and execute generated tests and detect crashes (segfaults), aborts, all kinds of emitted signals, non-zero program return code and program hanging.

例子:

fontconfig 2.8.0测试套件 FreeType 2.4.8的测试套件

我个人喜欢谷歌测试框架。

测试C代码的真正困难在于打破对外部模块的依赖,这样就可以将代码分离成单元。当您试图围绕遗留代码进行测试时,这可能尤其成问题。在这种情况下,我经常发现自己在测试中使用链接器来使用存根函数。

这就是人们在谈论“接缝”时所指的东西。在C语言中,你唯一的选择就是使用预处理器或链接器来模拟依赖项。

在我的一个C项目中,典型的测试套件可能是这样的:

#include "myimplementationfile.c"
#include <gtest/gtest.h>

// Mock out external dependency on mylogger.o
void Logger_log(...){}

TEST(FactorialTest, Zero) {
    EXPECT_EQ(1, Factorial(0));
}

注意,您实际上包含的是C文件,而不是头文件。这提供了访问所有静态数据成员的优势。这里我模拟了我的记录器(可能在logger中)。O并给出一个空的实现。这意味着测试文件独立于其余代码库进行编译和链接,并独立执行。

至于交叉编译代码,您需要在目标上使用良好的工具。我使用googletest交叉编译到PowerPC体系结构上的Linux来实现这一点。这是有意义的,因为您有一个完整的shell和os来收集结果。对于不太丰富的环境(我将其归类为没有完整操作系统的任何环境),您应该只在主机上构建和运行。无论如何您都应该这样做,这样您就可以作为构建的一部分自动运行测试。

我发现测试c++代码通常要容易得多,因为OO代码通常比过程性代码耦合得少(当然这在很大程度上取决于编码风格)。此外,在c++中,你可以使用依赖注入和方法重写等技巧来将接缝插入封装的代码中。

Michael Feathers有一本关于测试遗留代码的优秀书籍。在其中一章中,他介绍了处理非oo代码的技巧,我强烈推荐这些技巧。

编辑:我写了一篇关于单元测试过程代码的博客文章,源代码可以在GitHub上找到。

编辑:Pragmatic Programmers出版了一本新书,专门介绍了C代码的单元测试,我强烈推荐这本书。

这是CUnit

嵌入式单元是嵌入式C系统的单元测试框架。它的设计抄袭了JUnit和CUnit等,然后为嵌入式C系统做了一些调整。嵌入式单元不需要标准C库。所有对象都分配到const区域。

Tessy自动化了嵌入式软件的单元测试。