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瀏覽器進行打開,谷歌瀏覽器和狐火瀏覽器都無法正確打開。

在這裏插入圖片描述
在這裏插入圖片描述

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