现在常用的C++单元测试框架有 CppUnit,CxxTest,boost::test和google test。不像java/C#的测试框架,由于C++不支持reflection,所以,必须要做一些额外的工作,让框架知道相关内容的存在。CppUnit的做法是用宏进行注册。这种做法要求我们每添加一个测试,就要考虑用相应的宏进行注册,这种做法很繁琐,最大的问题在于由于疏忽而遗漏,这种靠人工保证的东西不可靠。在这点上,CxxTest 做得要好一些,有一个专门的脚本做这件事。通过这个脚本扫描这个自己编写的文件,生成一些新的文件,完成这个工作。从代码的表现力和可靠度来说,要好得多。唯一的问题是引入了一个脚本,而且这个脚本一般是由某些动态语言写成的(目前的CxxTest有Perl和Python的脚本),从而引入了对这种语言的依赖。而boost::test和google test 则是通过一些宏机制,来实现用户只需写一次就可以自动完成注册。
我大概分析了一下gtest的实现机制。由于里面用了很多宏,比较费解,因此首先用cl /P /C命令将之展开,我的测试程序如下
google test初步分析#include <gtest/gtest.h>
}

宏展开完后主要部分如下
google test初步分析class FactorialTest_Negative_Test : public ::testing::Test
}


可以看出,gtest是利用static变量的初始化来实现函数注册的,主要函数为MakeAndRegisterTestInfo(),该函数定义在src\gtest.cc里面
google test初步分析TestInfo* MakeAndRegisterTestInfo(
google test初步分析    
const char* test_case_name, const char* name,
google test初步分析    
const char* test_case_comment, const char* comment,
google test初步分析    TypeId fixture_class_id,
google test初步分析    SetUpTestCaseFunc set_up_tc,
google test初步分析    TearDownTestCaseFunc tear_down_tc,
google test初步分析    TestFactoryBase
* factory)
}

果然不出所料,GetUnitTestImpl()->AddTestInfo(xx)这一句就是做注册,下面我仿照gtest自己写了一个简单的测试框架
google test初步分析#include <string>
google test初步分析#include 
<vector>
google test初步分析#include 
<iostream>
google test初步分析
using namespace std;
google test初步分析
google test初步分析
class Test
    \


使用该测试框架的方法如下

google test初步分析TEST(test1)
}


输出结果:

I:\VC2008\gtest-1.2.1>mySimulate.exe
start test..
.
AssertFail:2==1 File:mySimulate.cpp Line:66 Function:test1
.
AssertFail:2==3 File:mySimulate.cpp Line:72 Function:test2

尚有点问题就是,现实的错误行号其实为函数第一行的行号。

相关文章: