Welcome

首页 / 软件开发 / C++ / 从Google开源RE2库学习到的C++测试方案

从Google开源RE2库学习到的C++测试方案2014-11-11最近因为科研需求,一直在研究Google的开源RE2库(正则表达式识别库),库源码体积庞大,用C++写的,对于我这个以前专供Java的人来说真的是一件很痛苦的事,每天只能啃一点点。今天研究了下里面用到的测试方法,感觉挺好的,拿来跟大家分享下!(哈~C++大牛勿喷)

对于我这个C++菜鸟中的菜鸟而言,平时写几个函数想要测试一般都是在main中一个一个的测试,因为没用C++写过项目,没有N多方法所以在main中一个个测试也不费劲。但是对于一个项目而言,或多或少都有N多方法,如果在main中一个个测试的话,不仅效率低而且还容易出错遗漏什么的。那么该怎么进行测试呢?貌似现在有很多C++自动化测试的工具,反正我是一个没用过,也没法评价。我就说下Google在RE2库里是怎么测试的吧。

先用一个超级简单的例子来做讲解:测试两个方法getAsciiNum()和getNonAsciiNum(),分别求flow中ASCII码字符的数目和非ASCII码字符的数目。

第一步:写个头文件,定义测试所用类和测试方法。

// test.h#define TEST(x, y) void x##y(void); TestRegisterer r##x##y(x##y, # x "." # y); void x##y(void)void RegisterTest(void (*)(void), const char*);class TestRegisterer {public:TestRegisterer(void (*fn)(void), const char *s) {RegisterTest(fn, s);}};
解析:首先看定义的类TestRegisterer,有个构造方法,两个参数:

1. 一个函数指针:void (*fn)(void),指向我们具体要编写的测试方法名;

2. 一个字符串:constchar *s,属于该测试方法的描述信息。

这个构造函数调用了另一个函数RegisterTest(),具体实现见下面。

然后看最上面定义的宏TEST(x, y),主要将其替换为TestRegisterer r##x##y(x##y, # x"." # y);其中x##y作为方法名,# x"." # y作为描述信息。这里可能有些和我一样入门级别的人没怎么看懂这个宏,因为不知道前后加void x##y(void);这个是干嘛用的?一开始我也没想明白,因为不加的话就会报错,后来通过gcc的-E选项激活宏编译,看了下编译期间展开成啥模样了。这里以一个简单的例子作为说明:假设x为test,y为flow,如果不加前后那个,那么展开后为TestRegisterer rtestflow(testflow, "test.flow"); 这明显是个函数声明,有两个参数,第二个是字符串,那么第一个是什么?编译器会认为是个函数名(实际上也是的),但这个函数前面明显未定义,就会报找不到此函数声明的错误,所以就需要在之前加上void x##y(void);声明函数,当然光声明不实现在链接时同样报错,所以就需要在之后加上void x##y(void)进行具体实现了,注意这里没有逗号,也没有具体实现的{},因为这只是宏,Google的所有测试函数是这样写的:

TEST(x, y) { ....// 具体实现 }
那么上面例子TEST(test, flow){ ...  // 具体实现 },整体展开后就是这样:

void testflow(void);TestRegisterer rtestflow(testflow, "test.flow");void testflow(void) { ....// 具体实现 }