【测试】Cunit单元测试
目录
相关教程
《CUnit使用流程简介》
http://www.51testing.com/html/18/297918-867415.html
《CUnit使用教程》
http://blog.sina.com.cn/s/blog_77f51a340100qf6k.html
1.CUnit介绍:
CUnit是完成测试的自动化工具,编写一定的代码就可以完成对工程的单元测试,包含N个suit,每个suit下面又有很多test。
2.工具准备:
a) CUnit的库及头文件
b)Eclipse(配置了CDT---支持C/C++)
c) 编译器MinGW或者安装cygwin来配置gcc。
3.编写项目:
下面以一个测试maxi函数为例进行介绍CUnit是如何进行自动化单元测试的。
首先工程需要如下三个文件:
test.c:表示需要测试的函数。
int maxi(int x, inty)
{
if(x > y)
{
return x;
}
else
return y;
}
Testcase.c:表示测试用例
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Automated.h"
#include"CUnit.h"
#include"TestDB.h"
extern int maxi(inti, int j);
void testILJ()
{
CU_ASSERT_EQUAL(maxi(1, 2), 2);
CU_ASSERT_EQUAL(maxi(-1, 0), 0);
CU_ASSERT_EQUAL(maxi(-2, -1), -1);
}
void testIQJ()
{
CU_ASSERT_EQUAL(maxi(1, 1), 1);
CU_ASSERT_EQUAL(maxi(0, -0), 0);
}
void testIGJ()
{
CU_ASSERT_EQUAL(maxi(2, 1), 2);
CU_ASSERT_EQUAL(maxi(0, -1), 0);
CU_ASSERT_EQUAL(maxi(-1, -2), -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;
}
CU_SuiteInfo suites[] = //一个测试suite init-->testcase-->clean
{
{"Testing the functionmaxi:", suite_success_init, suite_success_clean, testcases},
CU_SUITE_INFO_NULL
};
void AddTests(void)
{
assert(NULL != CU_get_registry());
assert(!CU_is_test_running());
if(CUE_SUCCESS != CU_register_suites(suites)) //注册测试suite
{
fprintf(stderr, "Register suites failed - %s ", CU_get_error_msg());
exit(EXIT_FAILURE);
}
}
main.c:函数入口。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include "Basic.h"
#include "Automated.h"
#include "Console.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);
if (argc > 1)
{
if (!strcmp("-i", argv[1]))
{
CU_set_error_action(CUEA_IGNORE);
}
else if (!strcmp("-f", argv[1]))
{
CU_set_error_action(CUEA_FAIL);
}
else if (!strcmp("-A", argv[1]))
{
CU_set_error_action(CUEA_ABORT);
}
else if (!strcmp("-e", argv[1]))
{
// print_example_results();00
}
else
{
printf("\nUsage: AutomatedTest [option]\n\n"
" Options: -i Run, ignoring framework errors [default].\n"
" -f Run, failing on framework error.\n"
" -A Run, aborting on framework error.\n"
" -e Print expected test results and exit.\n"
" -h Print this message.\n\n");
}
}
else
{
CU_set_error_action(error_action);
}
if (CU_initialize_registry()) {
printf("初始化错误");
}
else
{
AddTests();
CU_basic_set_mode(CU_BRM_VERBOSE);
printf("\nTests completed with return value %d.\n", CU_basic_run_tests());
CU_set_output_filename("DcmTest");
CU_list_tests_to_file();
CU_automated_run_tests(); */
CU_cleanup_registry();
}
return 0;
}
完成以上代码的编写,整个项目的代码就编写完毕了,值得一提的是,CUnit中包含了四种显示模式,只研究了显示在控制台和显示成xml文件的两种形式。上述main中演示了两种方式的代码部分。
当然工程设置结束,任务并没有结束,我们还需要完成项目的头文件设置和库链接。
头文件设置:
值得注意的是,这里一定要设置成GNU C,因为我们使用的是GCC。而且一定要查找到头文件的最底层文件夹。
库设置:设置CUnit库所在的文件夹。
编译器设置:这里选用的是cygwin GCC和GNU builder。
需要注意的是需要将CUnit的libcunit.dll复制到system32文件夹下。否则需要设置Path指向libcunit.dll所在的位置。
这样,整体的配置就完成了,剩下的只是享受CUnit进行单元测试所带来的方便和快捷。
运行结果
如何使用CUnit进行单元测试和覆盖率统计
https://www.jianshu.com/p/b0bffd44d2c9
http://blog.chinaunix.net/uid-25242461-id-5784456.html
3.CUNIT结构框架
CUnit的测试是单线程启动,只能注册一个Test Registry, 一次测试(Test Registry)可以运行多个测试包(Test Suite),而每个测试包可以包括多个测试用例(Test Case),每个测试用例又包含一个或者多个断言类的语句。具体到程序的结构上,一次测试下辖多个Test Suite,它对应于程序中各个独立模块;一个Suite管理多个Test Case,它对应于模块内部函数实现。每个Suite可以含有setup和teardown函数,分别在执行suite的前后调用。
注册一个测试用例(如果已经注册了你可以cleanup掉然后重新注册使用)然后CU_add_suite增加你的模块然后CU_add_test再在你的模块下挂载你的模块内的测试函数。所有的挂载完毕后,调用你想使用的界面进行测试。
《C开发中的单元测试(CUNIT)》 函数有注释
https://blog.csdn.net/zjuxsl/article/details/49780801
单元测试是什么,什么时候需要单元测试
(https://blog.csdn.net/qq_21517413/article/details/88757522)
单元测试是什么
什么时候需要单元测试
不需要:
小的代码量,简单固定的需求,个人开发,一锤子买卖等等都会让单元测试显得不那么重要。
需要:
较大的项目,项目的需求很多,一直在开发/修改,遇到了这样的痛苦状况:
1.客户总能在使用中找出BUG,
2.每次代码的改动,都会导致一些意想不到的BUG出现。
这个时候,单元测试可以挽救你。
记住,单元测试的威力更多不是体现在新代码的编写上,而是对已有代码的更改。
既:
”
增量还是存量
- 单测case针对增量代码
- 当存量代码出现大规模重构,后者质量暴露出极大风险时,都是推动补全单测的好时机
”
单元测试代码多码
事实上单元测试代码都是异常简单的一些“断言”代码,断言就是判断一个函数或对象的一个方法所产生的结果是否等于你期望的那个结果,这样的代码看起来很多,但事实上书写的成本很低。
单元测试分类
(链接:https://www.zhihu.com/question/28729261/answer/1058317111)
小型测试、中型测试和大型测试。
- 小型测试,针对单个函数的测试,关注其内部逻辑,mock所有需要的服务。小型测试带来优秀的代码质量、良好的异常处理、优雅的错误报告
- 中型测试,验证两个或多个制定的模块应用之间的交互
- 大型测试,也被称为“系统测试”或“端到端测试”。大型测试在一个较高层次上运行,验证系统作为一个整体是如何工作的。
结论:我们的单元测试,既可以针对一个函数写case,也可以按照函数的调用关系串起来写case。 金字塔模型