CUnit使用入门-精简的C语言单元测试工具

目的:通过一个示例演示,掌握用Cunit做单元测试
内容:
1、介绍Cunit架构
2、介绍Cunit的测试模式
3、实例演示用Cunit 写单元测试的操作流程

1.Cunit架构
Test Registry

|

|                  |
Suite '1' . . . . Suite 'N'
|                  |

           | |                 | |

Test ‘11’ … Test ‘1M’ Test ‘N1’ … Test ‘NM’
提到这个框架,为后面如何使用CUnit提供了基础。
先介绍这个框架,从底层往上介绍就两句话:
(1)每个测试用例被包装在一个测试包(suite)中,
(2)每个测试包(suite)是在有效的测试注册单元(Test Registry)中注册的。
对于CUnit来说,它是单线程运行,所以每次只能有一个有效的测试注册单元(Test Registry),这个测试注册单元下面可以包含多个测试包(suite),每个测试包可以拥有多个测试用例。划分测试包(suite)的规则可以自由约定,比如按照模块来划分,一个模块的测试用例集中到一个测试包中(suite)。至于测试用例,则用来测试模块内部的函数。测试用例函数通过提供的各类输入调用被测试的函数,返回执行结果,然后通过CUnit提供的断言来判断被测试的函数是否正确。
2.Cunit的测试模式
1 Automated Output to xml file Non-interactive
2 Basic Flexible programming interface Non-interactive
3 Console Console interface (ansi C) Interactive
4 Curses Graphical interface (Unix) Interactive
第一种模式是将结果输出到XML文档中,便于生成报告。
第二种模式是每一次运行结束之后在standard output中显示测试结果,不能保留测试结果数据。
第三种模式是console方式的,可以人机交互;前两种模式是非交互式的。第四种只在Unix中使用。

3.实例演示用Cunit写单元测试的操作流程
1) 编写单元测试函数(有必要的话要写suite的init/cleanup函数)。Write functions for tests (and suite init/cleanup if necessary).
2) 调用函数CU_initialize_registry()初始化测试注册单元(Test Registry)。 Initialize the test registry - CU_initialize_registry()
3) 调用函数CU_add_suite() 将测试包(suite)添加到测试注册单元(Test Registry)中。Add suites to the test registry - CU_add_suite()
4) 调用函数CU_add_test()将测试用例添加到测试包(suite)中。Add tests to the suites - CU_add_test()
5) 使用合适的接口来运行测试用例。Run tests using an appropriate interface, e.g. CU_console_run_tests
6) 调用函数CU_cleanup_registry清除测试注册单元(Test Registry)。Cleanup the test registry - CU_cleanup_registry()

4.Linux系统下用Cunit来进行单元测试
1.编译CUnit,编译后,头文件目录在/root/local/include/CUnit中,静态库文件在/root/local/lib/下。
(1)用root用户登录,下载CUnit-2.1-0-src.tar.gz。
(2)tar -zxvf CUnit-2.1-0-src.tar.gz
(3)cd CUnit-2.1-0
(4)./configure –prefix=$HOME/local
(5)make
(6)make install
2.编写一个Makefile文件,放入到在源文件目录中
2.Linux可执行文件执行时找不到共享库的解决办法
错误信息:error while loading libraries: libcunit.so.1 :cannot open shared object file:No such file or directory

1>ldd 命令查看编译生成的可执行文件发现:
linux-gate.so.1 => (0x00498000)
libcunit.so.1 => not found
libc.so.6 => /lib/libc.so.6 (0x00b6f000)
/lib/ld-linux.so.2 (0x00b4b000)
2>修改/etc/ld.so.conf,添加libcunit.so.1的存放目录/root/local/lib
3>Ldconfig
4>再次执行ldd命令
linux-gate.so.1 => (0x00a98000)
libcunit.so.1 => /root/local/lib/libcunit.so.1 (0x0068c000)
libc.so.6 => /lib/libc.so.6 (0x00b6f000)
/lib/ld-linux.so.2 (0x00b4b000)
5>原理:
编译时确实是通过了,因为你编译时指定了编译时需要的有关该共享库的信息。
但是没有指定运行时(run time)所需要的信息。ldconfig creates the necessary links and cache to the most recent shared libraries found in the directories specified on the command line, in the file /etc/ld.so.conf, and in the trusted directories (/lib and /usr/lib). The cache(/etc/ld.so.cache
) is used by the run-time linker, ld.so or ld-linux.so.
需要的动态链接库的目录路径,必须在/etc/ld.so.cache 文件中,而该文件是通过ld.so.conf指定的目录,以及信任目录(/lib and /usr/lib),使用ldconfig命令生成的。ldd命令也查看可执行文件所依赖的动态库信息时,也使用了/etc/ld.so.cache文件,因此在没有将所需要的动态库目录添加到ld.so.conf中且执行ldconfig时,会提示该库”not found”

4:源代码

⑴被测函数test.c
/**
*file:test.c
**/
int maxi(int i,int j)
{
    return i>j?i:j;
}
⑵测试函数(定义测试用例和测试包)testcase.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <CUnit/CUnit.h>
#include <CUnit/Automated.h>
#include <CUnit/TestDB.h>
/**//*---- functions to be tested ------*/
extern int maxi(int i, int j);
/**//*---- test cases ------------------*/
void testIQJ()
{
    CU_ASSERT_EQUAL(maxi(11),1);
    CU_ASSERT_EQUAL(maxi(0,-0),0);
}
void testIGJ()
{
    CU_ASSERT_EQUAL(maxi(21),2);
    CU_ASSERT_EQUAL(maxi(0,-1),0);
    CU_ASSERT_EQUAL(maxi(-1,-2),-1);
}
void testILJ()
{
    CU_ASSERT_EQUAL(maxi(12),2);
    CU_ASSERT_EQUAL(maxi(-10),0);
    CU_ASSERT_EQUAL(maxi(-2,-1),-1);
}
CU_TestInfo testcases[] = {
    {"Testing i equals j:", testIQJ},
    {"Testing i greater than j:", testIGJ},
    {"Testing i less than j:", testILJ},
    CU_TEST_INFO_NULL
};
/**//*---- test suites ------------------*/
int suite_success_init(void)
{ return 0; }
int suite_success_clean(void)
{ return 0; }
CU_SuiteInfo suites[] = {
    {
        "Testing the function maxi:",      suite_success_init,              suite_success_clean,
         testcases
     },
    CU_SUITE_INFO_NULL
};
/**//*---- setting enviroment -----------*/
void AddTests(void)
{
    assert(NULL != CU_get_registry());
    assert(!CU_is_test_running());
/**//* shortcut regitry */
    if(CUE_SUCCESS != CU_register_suites(suites)){
            fprintf(stderr, "Register suites failed - %s ", CU_get_error_msg());
    exit(EⅪT_FAILURE);
    }
}
⑶运行测试函数 Main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "Basic.h"
int main(int argc, char* argv[])
{
    CU_BasicRunMode mode = CU_BRM_VERBOSE;
    CU_ErrorAction error_action = CUEA_IGNORE;
    int i;
    setvbuf(stdout, NULL, _IONBF, 0);
    for (i=1 ; i<argc ; i++) {
        if (!strcmp("-i", argv)) {
            error_action = CUEA_IGNORE;
        }
        else if (!strcmp("-f", argv)) {
            error_action = CUEA_FAIL;
        }
        else if (!strcmp("-A", argv)) {
            error_action = CUEA_ABORT;
        }
        else if (!strcmp("-s", argv)) {
            mode = CU_BRM_SILENT;
        }
        else if (!strcmp("-n", argv)) {
            mode = CU_BRM_NORMAL;
        }
        else if (!strcmp("-v", argv)) {
            mode = CU_BRM_VERBOSE;
        }
        else if (!strcmp("-e", argv)) {
            return 0;
        }
        else {
            printf("\nUsage:BasicTest [options]\n\n"
            "Options:-i ignore framework errors [default].\n"
            " -f fail on framework error.\n"
            " -A abort on framework error.\n\n"
            " -s silent mode - no output to screen.\n"
            " -n normal mode - standard output to screen.\n"
            " -v verbose mode - max output to screen [default].\n\n"
            " -e print expected test results and exit.\n"
            " -h print this message and exit.\n\n");
            return 0;
    }
}
if (CU_initialize_registry()) {
    printf("\nInitialization of Test Registry failed.");
}
else {
        AddTests();
        CU_basic_set_mode(mode);
        CU_set_error_action(error_action);
        printf("\nTests completed with return value %d.\n", CU_basic_run_tests());
        CU_cleanup_registry();
    }
    return 0;
}
⑷Makefile
INC=-I/usr/local/include/CUnit
LIB=-L/usr/local/lib/
all:func.c test_func.c run_test.c
#gcc -o test $(INC) $(LIB) -lcunit $^
gcc -o test $(INC) $(LIB) -lcunit  $^
clean:
-rm -rf *.o test
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值