持续完善 Pinda.cn 秒建营销活动 通过低代码 零代码的模式快速创建营销活动,欢迎使用 。

介绍一个轻量级的C++ Unit test 框架: TUT

  无论你是否采用测试驱动开发(TDD),编写Unit test case都是重要的工作.在项目的各个阶段,我们都需要构建测试、运行测试、报告测试结果. 有很多框架为这个工作提供便利,比如大名鼎鼎的xUnit系列.今天,我准备介绍的是一个轻量级的C++ Unit Test框架:TUT (Template Unit Tests的缩写)

   大家第一个想问的问题估计就是:它和CppUnit有什么不同? 它有什么特点?
   我觉得最关键的地方在于TUT是一个轻量级的框架,TUT是使用template技术写的,完全没有macro. 除去例子,它的代码一共只有两个头文件.我们完全不用build这个框架然后设置编译连接那么多麻烦,只要在编写Unit test的时候,把这两个头文件拷贝到项目目录或者设置一下头文件的包含路径就可以了.

  TUT把Unit test case通过group-test的层次组织,用户可以把相似的test case放到同一个group,这个group有一个唯一的名字, group包含多个test, 包含的test数量取决于你的编译器允许的template嵌套深度.用户可以选择运行所有的测试或者只是部分group,甚至部分test. 在每个test里面,你可以使用TUT提供的一些方法来确认测试结果的正确性,告诉TUT这个测试是成功还是失败.

   闲话少说,估计大家喜欢眼见为实,让我们写个例子来看看:

   1. 首先包含必要的头文件
#include <stdio.h>
#include "tut.h"
#include "tut_reporter.h"


  2. 接着写了一个测试class

//测试类,做的事情很简单,记住给它的最大的数字,我们就测试这个类
class max_pool
{

int
m_max;
public
:
max_pool(int x=5) : m_max(x){ printf("%s init max num %d\n", __func__, x); }
void
try_set_value(int num) { if (num>m_max) m_max = num; }
int
get_max() { return m_max; }
};
   3. 写关于test group的代码 
/*这个类用在test_basic里面,
我们可以用它来完成一些每个test都需要做的初始化和清理工作,
不过这里只是为了说明, 只是输出点文字
*/

class
obj_init
{

public
:
obj_init() { printf( "obj_init for each test\n" ); }
~
obj_init() { printf( "~obj clean for each test\n" ); }
};

namespace tut
{

struct
test_basic
{

max_pool m;
obj_init xxx;
};
//每个测试用例,都会重新构造和析构test_basic里面的m 和 xxx,
//假如有什么需要每个测试都需要初始化和销毁的,放在这里

typedef test_group<test_basic> factory;
typedef factory::object object;

factory tf("max_poll_test_name");//这里设置了测试group的名字
}

4. 写两个test case
namespace tut
{

/**
* Checks insert operation
*/

template
<>
template
<>
void
object::test<1>()
{

printf("\trun test case <1>\n");
m.try_set_value(4);
ensure( m.get_max()==5 );//告诉TUT假如这里==5就是测试OK
}

template
<>
template
<>
void
object::test<2>()
{

printf("\trun test case <2>\n");
m.try_set_value(8);
ensure( m.get_max()==8 );//告诉TUT假如这里==8就是测试OK

}
}

5.终于写到main()了,运行所有测试:

using tut::reporter;
using tut::groupnames;
namespace tut
{
test_runner_singleton runner;
}
int main()
{
reporter visi;
tut::runner.get().set_callback(&visi);
tut::runner.get().run_tests();
    return 0;
}

编译...结果我用的EditPlus+cygwin组合编译出现了问题,说我的template嵌套层次太多。看看tut.h:
template <class Data, int MaxTestsInGroup = 50>
class test_group : public group_base { ...
 
原来是 test_group<test_basic> 缺省有50个test,也就是说编译器需要能支持50层的template嵌套, 
我修改了一下typedef test_group<test_basic,15> factory; 这样编译器只要能支持15层嵌套就可以通过了。
大家注意,VC6也是无法兼容TUT的,需要VS2003或者以上版本的支持.
 
最后运行的结果当然是测试通过了,结果如下, 大家可以注意到struct test_basic里面对象在每个test的输出:
 
max_pool init max num 5obj_init for each test
        run test case <1>~obj clean for each test
max_poll_test_name: .max_pool init max num 5
obj_init for each test
        run test case <2>
~obj clean for each test.max_pool init max num 5
obj_init for each test
~obj clean for each test
posted @ 2007-10-12 13:30  工具人Kim哥  阅读(1144)  评论(0编辑  收藏  举报
持续完善 Pinda.cn 秒建营销活动 通过低代码 零代码的模式快速创建营销活动,欢迎使用 。