C语言单元测试CUnit

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.xmlCUnitAutomated-Results.xml文件。文件名是在不设定的情况下,使用默认文件名。

把项目生成的CUnitAutomated-Listing.xmlCUnitAutomated-Results.xml,与CUnit安装目录下的CUnit-List.dtdCUnit-List.xslCUnit-Run.dtdCUnit-Run.xsl,共六个文件,放到一个文件夹下,拷贝到window系统下,使用IE浏览器打开。

注意,要用IE浏览器进行打开,谷歌浏览器和狐火浏览器都无法正确打开。

在这里插入图片描述
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章