CUnit简介
CUnit是一个通过C语言编写单元测试框架,用于编写、管理和执行单元测试用例的测试系统。
官网:http://cunit.sourceforge.net/
帮助文档:http://cunit.sourceforge.net/documentation.html
有关CUnit框架的更多介绍,可以参阅CUnit用户手册:
官方英文版:http://cunit.sourceforge.net/doc/index.html
中文翻译版:https://blog.csdn.net/benkaoya/article/details/95887879
原文链接:https://blog.csdn.net/benkaoya/article/details/95870801
编译、安装CUnit
安装环境,Ubuntu 16.04
下载地址:https://sourceforge.net/projects/cunit/files/CUnit/
到官网下载最新版本的代码,本文编写时,最新版本为2.1-3
。
安装步骤:
# tar -xjvf CUnit-2.1-3.tar.bz2
# cd CUnit-2.1-3
# mv configure.in configure.ac
# aclocal
# autoconf
configure.ac:161: error: possibly undefined macro: AC_PROG_LIBTOOL
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
出现找不到libtool工具错误。
安装libtool工具:
# apt-get install libtool
成功执行autoconf
# autoconf
# automake
configure.ac:4: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see:
configure.ac:4: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_005fINIT_005fAUTOMAKE-invocation
configure.ac:158: error: required file './compile' not found
configure.ac:158: 'automake --add-missing' can install 'compile'
configure.ac:4: error: required file './install-sh' not found
configure.ac:4: 'automake --add-missing' can install 'install-sh'
configure.ac:4: error: required file './missing' not found
configure.ac:4: 'automake --add-missing' can install 'missing'
执行automake出现以上错误,根据提示,添加 --add-missing
# automake --add-missing
configure.ac:4: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see:
configure.ac:4: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_005fINIT_005fAUTOMAKE-invocation
configure.ac:158: installing './compile'
configure.ac:4: installing './install-sh'
configure.ac:4: installing './missing'
CUnit/Sources/Automated/Makefile.am:4: error: Libtool library used but 'LIBTOOL' is undefined
CUnit/Sources/Automated/Makefile.am:4: The usual way to define 'LIBTOOL' is to add 'LT_INIT'
CUnit/Sources/Automated/Makefile.am:4: to 'configure.ac' and run 'aclocal' and 'autoconf' again.
CUnit/Sources/Automated/Makefile.am:4: If 'LT_INIT' is in 'configure.ac', make sure
CUnit/Sources/Automated/Makefile.am:4: its definition is in aclocal's search path.
添加--add-missing执行automark后,还有错误提示,根据错误找问题。
需要从新执行一遍autoconf。
# autoconf
# automake
configure.ac:4: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_005fINIT_005fAUTOMAKE-invocation
configure.ac:161: error: required file './ltmain.sh' not found
CUnit/Sources/Framework/Makefile.am:20: warning: '%'-style pattern rules are a GNU make extension
CUnit/Sources/Test/Makefile.am:12: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
Examples/AutomatedTest/Makefile.am:13: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
Examples/BasicTest/Makefile.am:13: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
Examples/ConsoleTest/Makefile.am:13: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
Examples/CursesTest/Makefile.am:13: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
以上错误只要在configure.ac:161: error: required file './ltmain.sh' not found
这行提示中。
根据提示,百度一番,发现是libtoolize配置问题。
首先查看下libtoolize的版本,确定已安装了。
# libtoolize --version
libtoolize (GNU libtool) 2.4.6
Written by Gary V. Vaughan <[email protected]>, 2003
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
然后执行一下命令进行配置libtoolize
libtoolize --automake --copy --debug --force
接着再执行automake
# automake --add-missing
configure.ac:4: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see:
configure.ac:4: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_005fINIT_005fAUTOMAKE-invocation
configure.ac:158: installing './compile'
configure.ac:4: installing './missing'
CUnit/Sources/Automated/Makefile.am: installing './depcomp'
CUnit/Sources/Framework/Makefile.am:20: warning: '%'-style pattern rules are a GNU make extension
CUnit/Sources/Test/Makefile.am:12: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
Examples/AutomatedTest/Makefile.am:13: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
Examples/BasicTest/Makefile.am:13: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
Examples/ConsoleTest/Makefile.am:13: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
Examples/CursesTest/Makefile.am:13: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
没有错误之后,执行configure,并执行安装路径为当前目录的__install文件夹。
# ./configure --prefix=$PWD/__install
编译
# make
安装
# make install
# cd __install/
# tree ./
./
├── doc
│ └── CUnit
│ ├── CUnit_doc.css
│ ├── error_handling.html
│ ├── fdl.html
│ ├── headers
│ │ ├── Automated.h
│ │ ├── Basic.h
│ │ ├── Console.h
│ │ ├── CUCurses.h
│ │ ├── CUError.h
│ │ ├── CUnit.h
│ │ ├── CUnit_intl.h
│ │ ├── MyMem.h
│ │ ├── TestDB.h
│ │ ├── TestRun.h
│ │ ├── Util.h
│ │ └── Win.h
│ ├── index.html
│ ├── introduction.html
│ ├── managing_tests.html
│ ├── running_tests.html
│ ├── test_registry.html
│ └── writing_tests.html
├── include
│ └── CUnit
│ ├── Automated.h
│ ├── Basic.h
│ ├── Console.h
│ ├── CUError.h
│ ├── CUnit.h
│ ├── CUnit_intl.h
│ ├── MyMem.h
│ ├── TestDB.h
│ ├── TestRun.h
│ └── Util.h
├── lib
│ ├── libcunit.a
│ ├── libcunit.la
│ ├── libcunit.so -> libcunit.so.1.0.1
│ ├── libcunit.so.1 -> libcunit.so.1.0.1
│ ├── libcunit.so.1.0.1
│ └── pkgconfig
│ └── cunit.pc
└── share
├── CUnit
│ ├── CUnit-List.dtd
│ ├── CUnit-List.xsl
│ ├── CUnit-Run.dtd
│ ├── CUnit-Run.xsl
│ ├── Memory-Dump.dtd
│ └── Memory-Dump.xsl
└── man
└── man3
└── CUnit.3
11 directories, 44 files
编译、安装总结:
aclocal
autoheader
autoconf
automake
如果在automake过程中有文件丢失,则执行下面命令:
automake --add-missing
再次执行automake
如果出现错误:configure.in:161:required file './ltmain.sh' not found,则执行下面的命令:
libtoolize --automake --copy --debug --force
执行完上述步骤以后,查看是否生成了configure,如果有,则执行:
./configure
执行完上述步骤以后,查看是否生成了Makefile,如果有,则执行:
make
安装编译出的库:
sudo make install
使用CUnit
测试样例1:
使用CUnit的basic接口测试,在控制台打印测试结果。
#include <stdio.h>
#include <string.h>
#include "CUnit/Basic.h"
static FILE* temp_file = NULL;
/* suite初始化函数
* 打开临时文件
* 返回值:0:成功;其它:失败
*/
int init_suite1(void)
{
if(NULL == (temp_file = fopen("temp.txt", "w+"))) {
return -1;
} else {
return 0;
}
}
/* suite清除函数
* 关闭临时文件
* 返回值:0:成功;其它:失败
*/
int clean_suite1(void)
{
if(0 != fclose(temp_file)) {
return -1;
} else {
temp_file = NULL;
return 0;
}
}
/* 测试函数1
* 测试fprintf()
*/
void testFPRINTF(void)
{
int i1 = 10;
if(NULL != temp_file) {
CU_ASSERT(0 == fprintf(temp_file, ""));
CU_ASSERT(2 == fprintf(temp_file, "Q\n"));
CU_ASSERT(8 == fprintf(temp_file, "i1 = %d", i1));
}
}
/* 测试函数2
* 测试fread()
*/
void testFREAD(void)
{
unsigned char buffer[20];
if(NULL != temp_file) {
rewind(temp_file);
CU_ASSERT(9 == fread(buffer, sizeof(unsigned char), 20, temp_file));
CU_ASSERT(0 == strncmp(buffer, "Q\ni1 = 10", 9));
}
}
int main()
{
CU_pSuite pSuite = NULL;
//初始化CUnit注册表
if(CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
//向CUnit注册表添加单元
pSuite = CU_add_suite("Suite_1", init_suite1, clean_suite1);
if(NULL == pSuite) {
CU_cleanup_registry(); //清空注册表,释放内存
return CU_get_error(); //返回错误
}
//向单元添加测试用例
if((NULL == CU_add_test(pSuite, "test of fprintf()", testFPRINTF)) ||
(NULL == CU_add_test(pSuite, "test of fread()", testFREAD))) {
CU_cleanup_registry();
return CU_get_error();
}
//使用CUnit Basic接口运行所有测试单元
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();
return CU_get_error();
}
makefile文件
all:
gcc -o test1 test1.c -I/home/mq/learn/CUnit/install/CUnit-2.1-3/__install/include -L/home/mq/learn/CUnit/install/CUnit-2.1-3/__install/lib -lcunit -static
静态链接CUnit库,引入头文件路径。
# make
# ./test1
CUnit - A unit testing framework for C - Version 2.1-3
http://cunit.sourceforge.net/
Suite: Suite_1
Test: test of fprintf() ...FAILED
1. test1.c:44 - 8 == fprintf(temp_file, "i1 = %d", i1)
Test: test of fread() ...passed
Run Summary: Type Total Ran Passed Failed Inactive
suites 1 1 n/a 0 0
tests 2 2 1 1 0
asserts 5 5 4 1 n/a
Elapsed time = 0.000 seconds
结果表示,在单元Suite_1
的测试fprintf()
函数,测试不通过。
测试样例2:
使用CUnit的Automated接口测试,测试结果输出到XML文件中。
#include <stdio.h>
#include <string.h>
//#include "CUnit/Basic.h"
#include "CUnit/Automated.h"
static FILE* temp_file = NULL;
/* suite初始化函数
* 打开临时文件
* 返回值:0:成功;其它:失败
*/
int init_suite2(void)
{
if(NULL == (temp_file = fopen("temp.txt", "w+"))) {
return -1;
} else {
return 0;
}
}
/* suite清除函数
* 关闭临时文件
* 返回值:0:成功;其它:失败
*/
int clean_suite2(void)
{
if(0 != fclose(temp_file)) {
return -1;
} else {
temp_file = NULL;
return 0;
}
}
/* 测试函数1
* 测试fprintf()
*/
void testFPRINTF(void)
{
int i1 = 10;
if(NULL != temp_file) {
CU_ASSERT(0 == fprintf(temp_file, ""));
CU_ASSERT(2 == fprintf(temp_file, "Q\n"));
CU_ASSERT(8 == fprintf(temp_file, "i1 = %d", i1));
}
}
/* 测试函数2
* 测试fread()
*/
void testFREAD(void)
{
unsigned char buffer[20];
if(NULL != temp_file) {
rewind(temp_file);
CU_ASSERT(9 == fread(buffer, sizeof(unsigned char), 20, temp_file));
CU_ASSERT(0 == strncmp(buffer, "Q\ni1 = 10", 9));
}
}
//测试用例信息结构体
static CU_TestInfo test_infos[] = {
{"testFPRINTF", testFPRINTF},
{"testFREAD", testFREAD},
CU_TEST_INFO_NULL
};
//测试单元信息结构体
static CU_SuiteInfo suites[] = {
{"test2", init_suite2, clean_suite2, NULL, NULL, test_infos},
CU_SUITE_INFO_NULL
};
int main()
{
//CU_pSuite pSuite = NULL;
CU_ErrorCode error ;
//初始化CUnit注册表
if(CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
error = CU_register_suites(suites);
if(CUE_SUCCESS != error) {
CU_cleanup_registry();
return CU_get_error();
}
//使用CUnit Automated interface
CU_automated_run_tests();
CU_list_tests_to_file();
CU_cleanup_registry();
return CU_get_error();
}
# make
# ./test2
执行完毕后,在同级目录下,生成CUnitAutomated-Listing.xml
和CUnitAutomated-Results.xml
文件。文件名是在不设定的情况下,使用默认文件名。
把项目生成的CUnitAutomated-Listing.xml
和CUnitAutomated-Results.xml
,与CUnit安装目录下的CUnit-List.dtd
、CUnit-List.xsl
、CUnit-Run.dtd
和CUnit-Run.xsl
,共六个文件,放到一个文件夹下,拷贝到window系统下,使用IE浏览器打开。
注意,要用IE浏览器进行打开,谷歌浏览器和狐火浏览器都无法正确打开。