4.准备测试脚本,验证root@ubuntu:/home/mf/CUnit-2.1-3# aclocal
aclocal: warning: autoconf input should be named ‘configure.ac’, not ‘configure.in’
root@ubuntu:/home/mf/CUnit-2.1-3# autoconf
root@ubuntu:/home/mf/CUnit-2.1-3# automake
如果在automake过程中有文件丢失,则执行下面命令:automake --add-missing
root@ubuntu:/home/mf/CUnit-2.1-3# chmod u+x configure
root@ubuntu:/home/mf/CUnit-2.1-3#./configure --prefix=$HOME/local
(./configure --prefix 后面加路径可以需要你输入要安装的目录,目录的格式举例如下:/local
这里我是直接./configure,默认路径)
root@ubuntu:/home/mf/CUnit-2.1-3#make
root@ubuntu:/home/mf/CUnit-2.1-3#make install
(到这里位置,我们的cunit的源码库就安装好啦)
这里我准备了4个文件:Main.c test.c testcase.c Makefile
放在Linux 下面新建的 root@ubuntu:/home/mf/Desktop/cunittest目录下
#includetest.c 的代码如下:#include #include #include #include "Basic.h" extern void AddTests(void); int main(int argc, char* argv[]) { CU_BasicRunMode mode = CU_BRM_VERBOSE; CU_ErrorAction error_action = CUEA_IGNORE; int i; //标准库输出 无缓冲:不使用缓冲。每个 I/O 操作都被即时写入。buffer 和 size 参数被忽略。 setvbuf(stdout, NULL, _IONBF, 0); for (i=1 ; i if (!strcmp("-i", *argv)) { //错误发生时继续执行(默认) error_action = CUEA_IGNORE; } else if (!strcmp("-f", *argv)) { //错误发生时应系统停止 error_action = CUEA_FAIL; } else if (!strcmp("-A", *argv)) { //错误发生时系统应退出(EXIT) 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]nn" "Options:-i ignore framework errors [default].n" " -f fail on framework error.n" " -A abort on framework error.nn" " -s silent mode - no output to screen.n" " -n normal mode - standard output to screen.n" " -v verbose mode - max output to screen [default].nn" " -e print expected test results and exit.n" " -h print this message and exit.nn"); return 0; } } //CU_initialize_registry registry初始化//用户在调用任何其他CUnit函数之前调用本函数,如果不这样做可能会导致系统崩溃。 if (CU_initialize_registry()) { printf("nInitialization of Test Registry failed."); } else { AddTests(); //CU_basic_set_mode()设置运行模式 CU_basic_set_mode(mode); //CU_set_error_action设置错误发生时,系统的行为 CU_set_error_action(error_action); //CU_basic_run_tests 运行Tests Basic Mode 基本扩展编程方式 非交互式 printf("nTests completed with return value %d.n",CU_basic_run_tests()); // registry释放 CU_cleanup_registry(); } return 0; }
int maxi(int i,int j)
{
return i>j?i:j;
}
testcase.c 的代码如下:
#includeMakefile的代码如下:#include #include #include #include #include extern int maxi(int i , int j); void testIQJ(void) { //断言相等比较 CU_ASSERT_EQUAL(maxi(1,1),1); CU_ASSERT_EQUAL(maxi(0,-0),0); } void testIGJ(void) { CU_ASSERT_EQUAL(maxi(2,1),2); CU_ASSERT_EQUAL(maxi(0,-1),0); CU_ASSERT_EQUAL(maxi(-1,-2),-1); } void testILJ(void) { CU_ASSERT_EQUAL(maxi(1,2),2); CU_ASSERT_EQUAL(maxi(-1,0),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 }; int suite_success_init(void) { return 0; } int suite_success_clean(void) { return 0; } //需要运行的test case CU_SuiteInfo suites[] = { {"Testing the function maxi:",suite_success_init,suite_success_clean, NULL, NULL,testcases}, CU_SUITE_INFO_NULL }; void AddTests(void) { //1.CU_get_registry CU_register_suites其他一些关于注册的内部函数,主要用于内部和测试的目的 assert(NULL != CU_get_registry()); assert(!CU_is_test_running()); //注册suites if(CUE_SUCCESS != CU_register_suites(suites)){ fprintf(stderr, "Register suites failed - %s ", CU_get_error_msg()); exit(EXIT_FAILURE); } }
INC=-I/usr/local/include/CUnit LIB=-L/usr/local/lib all:Main.c test.c testcase.c gcc -o test $(INC) $(LIB) $^ -lcunit clean: -rm -rf *.o test
Makefile文件说明:
5.在linux的下面/home/mf/Desktop/cunittest目录执行make命令(1)INC=填写的是cuint的头文件的目录
(2)LIB=填写的是cunit的lib库的目录
(3)编译命令连接到头文件和lib库 生成可执行文件test
gcc -o test $(INC) $(LIB) $^ -lcunit
root@ubuntu:/home/mf/Desktop/cunittest# make
此时出现了如下错误:没有找到lib库
解决如下:
6.执行可执行文件(1)进入lib库的地址查看,cunit的lib库确实安装没有问题
(2)发现没有动态链接, 还需要设置动态库所在的位置
添加设置一个环境变量: export LD_LIBRARY_PATH=/usr/local/lib,操作如下:
- 打开profile文件添加环境变量
root@ubuntu:/etc# gedit /root/.profile
- 添加好后记得 source /root/.profile
- 修改完毕后,再次执行make,生成一个可执行文件,test
root@ubuntu:/home/mf/Desktop/cunittest# ./test
出现如下报错:
这里的段错误,程序内存出了问题,使用gdb方式进行调试,步骤如下:
- 默认coredump不会保存在磁盘上,需要执ulimit -c unlimited才可以
root@ubuntu:/home/mf/Desktop/cunittest# ulimit -c unlimited- 然后要 指定一下coredump的路径和格式:
root@ubuntu:/home/mf/Desktop/cunittest#echo “/tmp/core-%e-%p” > /proc/sys/kernel/core_pattern- 重新make,在执行./test后就会产生一个coredump了
- 进入coredump文件的目录
- 开启gdb调试
root@ubuntu:/tmp#gdb test.o /tmp/core-test-104138
这里显示导致错误的是signal SIGSEGV信号,一般都是数组越界、死循环或者对空容器进行某些操作导致的。这里想到程序编译的时候出现的警告信息,
继续(gdb) bt 可以看到是CU_register_suites(suites)这个函数出了问题,
函数本身应该没有错误,可能是传给他从参数 有问题,就是那个suites,该参数构建的代码如下:
CU_SuiteInfo suites[] = {
{"testSuite1", suite_success_init, suite_success_clean, testcase },
CU_SUITE_INFO_NULL
};
这个CU_SuiteInfo的数组没有构建正确,该结构有6个成员,但我们定义的时候只有4个成员,直接修改为(以上提供的testcase.c脚本代码已经是修改后正确的代码)
CU_SuiteInfo suites[] = {
{"testSuite1", suite_success_init, suite_success_clean,NULL, NULL, testcase },
CU_SUITE_INFO_NULL
};
7.问题解决后,我们在make,生成一个新的test可执行文件,直接./test运行,就会标准输出的方式,在界面输出测试结果啦(后面也可以改为xml方式显示测试结果到网页)



