C语言单元測试

摘要:
CUnit--CUnit是一个轻型的C语言单元測试框架。这里有一篇CUnit測试工具使用,还有一篇C单元測试包设计与实现讲的不错,能够看一下。它提供了一个简单的单元測试框架,而且为经常使用的数据类型提供了丰富的断言语句支持。

C语言单元測试

对于敏捷开发来说,单元測试不可缺少,对于Java开发来说,JUnit非常好,对于C++开发,也有CPPUnit可供使用,而对于传统的C语言开发,就没有非常好的工具可供使用,能够找到的有这么几个工具:

  1. CuTest -- CuTest(Cute Test)是一个很easy的C语言单元測试工具。在使用它的时候,仅仅须要包括两个文件“CuTest.c CuTest.h”,然后就能够写測试用例,进行測试了。它对用例差点儿没有管理功能,报表输出也很easy,能够用来试验单元測试的基本想法。
  2. CUnit -- CUnit是一个轻型的C语言单元測试框架。它提供了设计、管理、执行測试用例的功能。它的报表功能比較强大,可是比較麻烦,更适合于较大一些的项目。
  3. Check -- 不错的工具。
    在这里(http://www.laatuk.com/tools/testing_tools.html)给出了各种软件測试工具,没事能够研究一下。

CUnit

这里主要讲CUnit在Linux平台下的应用。这里有一篇 CUnit測试工具使用 ,还有一篇 C单元測试包设计与实现 讲的不错,能够看一下。CUnit的主页是 http://cunit.sourceforge.net/index.html
CUnit以静态库的形式提供给用户使用,用户编敲代码的时候直接链接此静态库就能够了。它提供了一个简单的单元測试框架,而且为经常使用的数据类型提供了丰富的断言语句支持。

CUnit基本架构

Test Registry
|
------------------------------
| |
Suite '1' . . . . Suite 'N'
| |
--------------- ---------------
| | | |
Test '11' ... Test '1M' Test 'N1' ... Test 'NM'

一次測试(Test Registry)能够执行多个測试包(Test Suite),而每一个測试包能够包括多个測试用例(Test Case),每一个測试用例又包括一个或者多个断言类的语句。详细到程序的结构上,一次測试下辖多个Test Suite,它相应于程序中各个独立模块;一个Suite管理多个Test Case,它相应于模块内部函数实现。每一个Suite能够含有setup和teardown函数,分别在执行suite的前后调用。

CUnit測试模式

CUnit使用四种不同的接口,供用户来执行測试和汇报測试结果:

  1. 自己主动输出到XML文件, 非交互式
  2. 基本扩展编程方式, 非交互式
  3. 控制台方式, 交互式
  4. Curses图形接口, 交互式

注意1和2是非交互式的,4仅仅能在Unix下使用,经常使用console,并且console是能够人机交互的。

CUnit測试流程

使用CUnit进行測试的基本流程例如以下所看到的:

  1. 书写代測试的函数(假设必要,须要写suite的init/cleanup函数)
  2. 初始化Test Registry - CU_initialize_registry()
  3. 把測试包(Test Suites)添�到Test Registry - CU_add_suite()
  4. 添�測试用例(Test Case)到測试包其中 - CU_add_test()
  5. 使用适当的接口来执行測试測试程序,比如 CU_console_run_tests()
  6. 清除Test Registry - CU_cleanup_registry()

CUnit使用范例

CUnit的在线文档是 http://cunit.sourceforge.net/doc/index.html ,上面有着具体的论述。这里以使用自己主动产生XML文件的接口为例,讲述CUnit-2.1-0在Linux平台下的使用。
我要測试的是整数求最大值的函数maxi,我使用例如以下文件组织结构:

  1. func.c :定义maxi()函数
  2. test_func.c :定义測试用例和測试包
  3. run_test.c :调用CUnit的Automated接口执行測试
  4. Makefile :生成測试程序。

这样组织的优点是,我们能够把各个功能分离,当要改变待測试函数的定义的时候,我们仅仅须要改动func.c,而要增减、改动測试用例,仅仅改动test_func.c就能够了,要使用CUnit提供的别的API,那就改动run_test.c。

它们的内容分别例如以下所看到的:

1) func.c

C语言单元測试第1张C语言单元測试第2张/**//**
C语言单元測试第3张*file:func.c
C语言单元測试第4张*
*/

C语言单元測试第5张
C语言单元測试第5张
intmaxi(inti,intj)
C语言单元測试第7张C语言单元測试第8张
...{
C语言单元測试第3张
//returni>j?i:j;
C语言单元測试第3张
returni;
C语言单元測试第4张}

2) test_func.c

C语言单元測试第12张C语言单元測试第13张/**//**
C语言单元測试第3张*file:test_func.c
C语言单元測试第4张*
*/

C语言单元測试第5张#include
<stdio.h>
C语言单元測试第5张#include
<stdlib.h>
C语言单元測试第5张#include
<assert.h>
C语言单元測试第5张#include
"CUnit/CUnit.h"
C语言单元測试第5张#include
"CUnit/Automated.h"
C语言单元測试第5张
C语言单元測试第22张C语言单元測试第23张
/**//*----functionstobetested------*/
C语言单元測试第5张
externintmaxi(inti,intj);
C语言单元測试第5张
C语言单元測试第26张C语言单元測试第27张
/**//*----testcases------------------*/
C语言单元測试第5张
voidtestIQJ()
C语言单元測试第29张C语言单元測试第30张
...{
C语言单元測试第3张CU_ASSERT_EQUAL(maxi(
1,1),1);
C语言单元測试第3张CU_ASSERT_EQUAL(maxi(
0,-0),0);
C语言单元測试第4张}

C语言单元測试第5张
C语言单元測试第5张
voidtestIGJ()
C语言单元測试第36张C语言单元測试第37张
...{
C语言单元測试第3张CU_ASSERT_EQUAL(maxi(
2,1),2);
C语言单元測试第3张CU_ASSERT_EQUAL(maxi(
0,-1),0);
C语言单元測试第3张CU_ASSERT_EQUAL(maxi(
-1,-2),-1);
C语言单元測试第4张}

C语言单元測试第5张
C语言单元測试第5张
voidtestILJ()
C语言单元測试第44张C语言单元測试第45张
...{
C语言单元測试第3张CU_ASSERT_EQUAL(maxi(
1,2),2);
C语言单元測试第3张CU_ASSERT_EQUAL(maxi(
-1,0),0);
C语言单元測试第3张CU_ASSERT_EQUAL(maxi(
-2,-1),-1);
C语言单元測试第4张}

C语言单元測试第5张
C语言单元測试第51张C语言单元測试第52张CU_TestInfotestcases[]
=...{
C语言单元測试第53张C语言单元測试第54张
...{"Testingiequalsj:",testIQJ},
C语言单元測试第55张C语言单元測试第56张
...{"Testingigreaterthanj:",testIGJ},
C语言单元測试第57张C语言单元測试第58张
...{"Testingilessthanj:",testILJ},
C语言单元測试第3张CU_TEST_INFO_NULL
C语言单元測试第4张}
;
C语言单元測试第5张
C语言单元測试第5张
C语言单元測试第63张C语言单元測试第64张
/**//*----testsuites------------------*/
C语言单元測试第65张C语言单元測试第66张
intsuite_success_init(void)...{return0;}
C语言单元測试第67张C语言单元測试第68张
intsuite_success_clean(void)...{return0;}
C语言单元測试第5张
C语言单元測试第70张C语言单元測试第71张CU_SuiteInfosuites[]
=...{
C语言单元測试第72张C语言单元測试第73张
...{"Testingthefunctionmaxi:",suite_success_init,suite_success_clean,testcases},
C语言单元測试第3张CU_SUITE_INFO_NULL
C语言单元測试第4张}
;
C语言单元測试第5张
C语言单元測试第5张
C语言单元測试第78张C语言单元測试第79张
/**//*----settingenviroment-----------*/
C语言单元測试第5张
C语言单元測试第5张
voidAddTests(void)
C语言单元測试第82张C语言单元測试第83张
...{
C语言单元測试第3张assert(NULL
!=CU_get_registry());
C语言单元測试第3张assert(
!CU_is_test_running());
C语言单元測试第86张C语言单元測试第87张
/**//*shortcutregitry*/
C语言单元測试第3张
C语言单元測试第89张C语言单元測试第90张
if(CUE_SUCCESS!=CU_register_suites(suites))...{
C语言单元測试第3张fprintf(stderr,
"Registersuitesfailed-%s ",CU_get_error_msg());
C语言单元測试第3张exit(EXIT_FAILURE);
C语言单元測试第93张}

C语言单元測试第4张}

3) run_test.c

C语言单元測试第95张C语言单元測试第96张/**//**
C语言单元測试第3张*file:run_test.c
C语言单元測试第4张*
*/

C语言单元測试第5张
C语言单元測试第5张#include
<stdio.h>
C语言单元測试第5张#include
<stdlib.h>
C语言单元測试第5张#include
<assert.h>
C语言单元測试第5张
C语言单元測试第5张
intmain(intargc,char*argv[])
C语言单元測试第105张C语言单元測试第106张
...{
C语言单元測试第107张C语言单元測试第108张
if(CU_initialize_registry())...{
C语言单元測试第3张fprintf(stderr,
"InitializationofTestRegistryfailed. ");
C语言单元測试第3张exit(EXIT_FAILURE);
C语言单元測试第111张C语言单元測试第112张}
else...{
C语言单元測试第3张AddTests();
C语言单元測试第3张CU_set_output_filename(
"TestMax");
C语言单元測试第3张CU_list_tests_to_file();
C语言单元測试第3张CU_automated_run_tests();
C语言单元測试第3张CU_cleanup_registry();
C语言单元測试第93张}

C语言单元測试第3张
return0;
C语言单元測试第4张}

4) Makefile

C语言单元測试第5张INC=-I/home/lirui/local/include
C语言单元測试第5张LIB
=-L/home/lirui/local/lib
C语言单元測试第5张
C语言单元測试第5张all:func
.ctest_func.crun_test.c
C语言单元測试第5张gcc-otest
$(INC)$(LIB)-lcunit-lcurses-static$^

因为CUnit是以库的形式提供的,所以我们在编译和链接的时候须要指明头文件和库所在的位置,又因为使用了Curses库,所以也要指定这个。

測试报告

执行上面产生的test程序,会在当前文件夹下产生两个xml文件:

  1. TestMax-Listing.xml :对測试用例的报告
  2. TestMax-Results.xml :对測试结果的报告

要查看这两个文件,须要使用例如以下xsl和dtd文件:CUnit-List.dtd和CUnit-List.xsl用于解析列表文件, CUnit-Run.dtd和CUnit-Run.xsl用于解析结果文件。这四个文件在CUnit包里面有提供,安装之后在$(PREFIX) /share/CUnit文件夹下,在我的配置其中,它在/home/lirui/local/share/CUnit文件夹下。在查看结果之前,须要把这六个文件:TestMax-Listing.xml, TestMax-Results.xml, CUnit-List.dtd, CUnit-List.xsl, CUnit-Run.dtd, CUnit-Run.xsl复制到一个文件夹下,然后用浏览器打开两个结果的xml文件就能够了。

1) TestMax-Listing.xml在IE其中显演示样例如以下:

list cases

2) TestMax-Results.xml在IE其中显演示样例如以下:

results

免责声明:文章转载自《C语言单元測试》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇MassDNS:跨域DNS枚举工具nodejs API下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

c语言中typeof关键字

为什么因为一个关键字而专门写一篇随笔呢?因为这个关键字在Linux里面地位非同一般!这个关键字typeof在linux内核里面使用非常广泛! 下面这两个等效声明,用于声明int类弄的变量atypeof(int) a;typeof('b') a; //相当于获取'b'的类型,定义一个变量a下面用于声明指针和数组typeof(int*) p1,p2;typeo...

python 抓取cisco交换机配置文件

#!/usr/bin/python import sys import time import os import pexpect now = time.strftime('%Y-%m-%d',time.localtime(time.time()))aa = open ('/home/hanlei/test/%s/log.txt' % now, "w")...

Jenkins和Gitlab CI/CD自动更新k8s中pod使用的镜像说明

Jenkins 使用Jenkins的话,完成的工作主要有如下步骤:1.从Gogs或Gitlab仓库上拉取代码2.使用Maven编译代码,打包成jar文件3.根据jar文件使用相对应的Dockerfile文件制作成Docker镜像4.把Docker镜像推送到Nexus上的Docker仓库(或者Harbor仓库)5.运行shell脚本,给k8s的master主...

MySQL备份恢复之mydumper

  Preface       In my previous two blogs,we have known about the tool of backing up MySQL db.I'm gonna use another tool named "MySQL Data Dumper" to do some test,here we go.   Int...

c语言-----劫持系统03

1. 回顾   在前2节我们已经实现了劫持原理、函数指针等一些概念,下面进行系统劫持 2. 工具   vs2017   Detours 3. windows如何创建一个进程?   (1)创建进程函数 CreateProcessW( LPCWSTR lpApplicationName, //执行程序名称 LPWSTR lpCom...

TIOBE 四月世界编程语言排行榜:C语言重回榜首

TIOBE 2012年4月世界编程语言排行榜已经发布。C语言超越了Java重回榜首;而Objective-C则一路飙升,超越了C#,占据了第4的位置;并且C++也重新回到第3的位置。而Python持续下滑,目前排名第8。 TIOBE2012年4月世界编程语言排行榜的前20名 从开发领域来讲,只要有合适的硬件驱动和API,C或者C++理论上是可以做任何开发的...