C语言单元测试框架——CUnit

C语言单元测试框架——CUnit

1、CUnit简介

CUnit 是一个通过 C 语言编写的用于编写、管理和执行单元测试用例的C语言单元测试框架。

它往往被编成库的形式(静态库或动态库)提供给用户测试代码进行使用,用户编写程序的时候直接链接此静态库就可以了。

它提供了一个简单的单元测试框架,并且为常用的数据类型提供了丰富的断言语句支持。
CUnit是平台无关的框架与各种用户接口的组合。核心框架为管理测试注册表,套件和测试用例提供了基本支持。用户接口便于与框架交互以运行测试和查看结果。CUnit的组织结构与传统的单元测试框架类似:在这里插入图片描述
单独的测试用例(Test)被打包到套件(Suite)中,这些套件又被注册到活动测试注册表(Test Registry)里。每个套件都有自己的构造和析构函数,这两个函数将在运行套件测试之前和之后被自动调用。注册表中的所有套件/测试用例,可以通过调用一个函数执行全部测试,也可以有选择性地执行部分测试。

2、CUnit安装

2.1、安装配置——Ubuntu

软件源中与CUnit相关的包有:

libcunit1 libcunit1-dev libcunit1-doc libcunit1-ncurses libcunit1-ncurses-dev

使用apt-get install安装即可。

2.2、安装步骤

tar -jxvf CUnit-2.1-3.tar.bz2
cd CUnit-2.1-3
libtoolize -f -c -i
aclocal
autoconf
autoheader
automake
chmod u+x configure
./configure --prefix=/opt/cunit
make
make install

2.3、安装文件

cunit安装成功后会生成4个文件夹:doc、include、lib、share

  • doc目录是一些简介以及使用说明。
  • includelib目录中是我们需要的头文件以及库文件。
  • share目录中有Automated模式下需要的文件。

3、CUnit使用介绍

3.1、输出方式

接口平台描述
AutomatedAll非交互式,输出XML文件
BasicAll非交互式,可选输出到stdout
ConsoleAll控制台交互方式,在用户控制下运行
CursesLinux/UnixCurses交互方式(图形界面),在用户控制下运行

如上边所示,后两种主要是interactive的接口,就是我们可以交互式地指定参数,然后观察结果。在我们具体的环境下,我们通常使用上面两种接口,第一种是将结果输出到XML文档中,便于我们生成报告。第二种仅仅是每一次运行结束之后,在standard output中显示,不能保留测试结果数据。

我们可以将前两种输出结合起来,自己测试的时候,使用Basic模式,生成报告的时候,使用Automated模式。

注:在Curse输出模式下需要联接 -lncurses

3.2、输出方式对应的接口函数

模式使用的接口函数
Basic#include “CUnit/Basic.h”
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
Automated#include “CUnit/Automated.h”
CU_list_tests_to_file();
CU_automated_run_tests();
Console#include “CUnit/Console.h”
CU_console_run_tests();
Curses#include “CUnit/CUCurses.h”
CU_curses_run_tests();

配置使用Basic模式,运行的结果如下。

cunit_basic.png

配置使用Automated模式,重新编译运行后会生成CUnitAutomated-Listing.xmlCUnitAutomated-Results.xml两个文件。文件名是在不设定的情况下,使用默认文件名。

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

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

TestMax-Results.xml
cunit_automated_result

TestMax-Listing.xml
cunit_automated_listing

3.3、测试函数的书写

1) 首先针对被测试的函数书写测试函数。

2) 初始化一个Registry。

3) 将特定的Suite加入到这个Registry中。可以为Suite指定初始化函数和清理函数。

4) 将测试函数加入到一个Suite中,这样,如果该测试函数的运行需要一些初始化条件,那么可以可以将代码加入到Suite的初始化函数中,当然不要忘记最后还要做对应的清理操作。

5) 使用相应的接口将测试结果输出。

6) 最后,清理Registry。

3.4、CUnit 断言

CUnit提供了大量的预定义的断言,针对几乎所有的C的标准类型,我们可以针对具体的需要检查的参数的类型进行选择。

CUnit 对断言定义如下:

断言描述
CU_ASSERT (int expression)
CU_ASSERT_FATAL (int expression)
CU_TEST (int expression)
CU_TEST_FATAL (int expression)
断言表达 expression 是 CU_TRUE(非零)
CU_ASSERT_TRUE (value)
CU_ASSERT_TRUE_FATAL (value)
断言值 value 是 CU_TRUE(非零)
CU_ASSERT_FALSE (value)
CU_ASSERT_FALSE_FATAL (value)
断言值 value 是 CU_FALSE(零)
CU_ASSERT_EQUAL (actual, expected)
CU_ASSERT_EQUAL_FATAL (actual, expected)
断言 actual (实际) == expected (预期)
CU_ASSERT_NOT_EQUAL(actual, expected)
CU_ASSERT_NOT_EQUAL_FATAL (actual,expected)
断言 actual (实际) != expected(预期)
CU_ASSERT_PTR_EQUAL (actual, expected)
CU_ASSERT_PTR_EQUAL_FATAL (actual,expected)
断言 指针 actual(实际) == expected (预期)
CU_ASSERT_PTR_NOT_EQUAL (actual,expected)
CU_ASSERT_PTR_NOT_EQUAL_FATAL (actual, expected)
断言 指针 actual(实际) != expected (预期)
CU_ASSERT_PTR_NULL (value)
CU_ASSERT_PTR_NULL_FATAL (value)
断言 指针 value == NULL
CU_ASSERT_PTR_NOT_NULL (value)
CU_ASSERT_PTR_NOT_NULL_FATAL (value)
断言 指针 value != NULL
CU_ASSERT_STRING_EQUAL (actual,expected)
CU_ASSERT_STRING_EQUAL_FATAL (actual, expected)
断言的实际和预期的字符串是等价的
strcmp
CU_ASSERT_STRING_NOT_EQUAL
(actual,expected)
CU_ASSERT_STRING_NOT_EQUAL_FATAL
(actual, expected)
断言字符串的实际和预期不同
CU_ASSERT_NSTRING_EQUAL (actual,expected, count)
CU_ASSERT_NSTRING_EQUAL_FATAL
(actual, expected, count)
断言的实际和预期的前count个字符是相同的
strncmp
CU_ASSERT_NSTRING_NOT_EQUAL
(actual,expected, count)
CU_ASSERT_NSTRING_NOT_EQUAL_FATAL
(actual, expected, count)
断言前count个字符的实际和预期的不同
CU_ASSERT_DOUBLE_EQUAL
(actual,expected, granularity)
CU_ASSERT_DOUBLE_EQUAL_FATAL
(actual, expected, granularity)
Assert that fabs(actual - expected) <= fabs(granularity)
Math library must be linked in for this assertion
CU_ASSERT_DOUBLE_NOT_EQUAL
(actual,expected, granularity)
CU_ASSERT_DOUBLE_NOT_EQUAL_FATAL
(actual, expected, granularity)
Assert that fabs(actual - expected) >fabs(granularity)
Math library must be linked in for this assertion
CU_PASS (message)注册一个指定的通过断言的消息。不可进行逻辑测试。
CU_FAIL (message)
CU_FAIL_FATAL (message)
注册一个指定的失败断言的消息。不可进行逻辑测试。

可以看到,每一种类型的断言都有FATAL和非FATAL两个函数,他们的区别是,非FATAL断言失败的时候,程序继续运行,而FATAL类型的断言失败之后,程序马上中止。通常我们使用非FATAL就可以了。

注意在我们的程序中,需要对返回值,out参数进行判断,对于是否是预想结果的判断的时候,一定要使用断言,而不要使用printf等等函数,一方面printf缺乏灵活性,另一方面,只有使用断言,结果报告中才会有对应的输出项。

CU_PASSCU_FAIL这两个断言比较特殊,它们仅仅表示测试程序运行到了这个地方。比如,在某些测试函数中,被测试的函数没有任何返回值等,我们为了证明这个函数已经被运行到了,我们使用以上两个函数。它们仅仅打印出一条消息,代表执行过。还有就是,它们也被输出。

4、CUnit使用实例

#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <CUnit/Automated.h>
#include <CUnit/Basic.h>
#include <CUnit/CUnit.h>
#include <CUnit/Console.h>
#include <CUnit/TestDB.h>
#include <assert.h>

int suite_success_init(void){
    return 0;
}

int suite_success_clean(void){
    return 0;
}
void test_fun1(void){
	//测试函数编写
}
void test_fun2(void){
	//测试函数编写
}
CU_TestInfo test_cases1[] = {
    {"test1", test_fun1}, 
    {"test2", test_fun2},
    CU_TEST_INFO_NULL
};
CU_TestInfo test_cases2[] = {
    CU_TEST_INFO_NULL
};

CU_SuiteInfo suites[] = {
    {"test_cases1:", suite_success_init, suite_success_clean, NULL, NULL, test_cases1},
    {"test_cases2:", suite_success_init, suite_success_clean, NULL, NULL, test_cases2},
    CU_SUITE_INFO_NULL
};

int main(int argc, char **argv)
{
    if (CU_initialize_registry()) {
        fprintf(stderr, " Initialization of Test Registry failed. ");
        exit(EXIT_FAILURE);
    } else {
		assert(NULL != CU_get_registry());
		assert(!CU_is_test_running());
		if (CUE_SUCCESS != CU_register_suites(suites)) {
			exit(EXIT_FAILURE);
		}
#if 0
		/**** Automated Mode *****************/
		CU_set_output_filename("TestMax");
		CU_automated_run_tests();
		CU_list_tests_to_file();
#else
		//***** Basice Mode *******************
		CU_basic_set_mode(CU_BRM_VERBOSE);
		CU_basic_run_tests();
#endif
        CU_cleanup_registry();
        return CU_get_error();
    }
    return 0;
}

makefile

all:
	gcc -o test testcase.c -I./include -L./lib -lcunit
  • 8
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值