levelDB源码笔记(1)-TEST

来源:互联网 发布:算法设计中文版 编辑:程序博客网 时间:2024/05/16 23:55

leveldb的TEST部分,是单元测试一个很标准的实现


一。对想要测试的目标(这里是BloomFilterPolicy类),建立一个对应的测试类BloomTest

class BloomTest { private:  const FilterPolicy* policy_;...... public:  BloomTest() : policy_(NewBloomFilterPolicy(10)) { }  void Add(const Slice& s){......}  bool Matches(const Slice& s) {......}.......};};
Test类最常见的写法,是包含一个测试目标的指针,一些测试相关功能的函数(这里是Add,Match等)

二。然后调用一个宏,宏的{}里通常调用BloomTest的成员函数,输出一些判定结果等。

TEST(BloomTest, EmptyFilter) {  ASSERT_TRUE(! Matches("hello"));  ASSERT_TRUE(! Matches("world"));}

宏TEST其实是这样定义的

#define TCONCAT(a,b) TCONCAT1(a,b)#define TCONCAT1(a,b) a##b#define TEST(base,name)                                                 \class TCONCAT(_Test_,name) : public base {                              \ public:                                                                \  void _Run();                                                          \  static void _RunIt() {                                                \    TCONCAT(_Test_,name) t;                                             \    t._Run();                                                           \  }                                                                     \};                                                                      \bool TCONCAT(_Test_ignored_,name) =                                     \  ::leveldb::test::RegisterTest(#base, #name, &TCONCAT(_Test_,name)::_RunIt); \void TCONCAT(_Test_,name)::_Run()
TEST宏做了3件事

1.继承base(即上面定义的BloomTest类)定义一个新类,类名为base_name。注意在继承的类中,将可以调用父类的public,pretected成员。

2. 新增两个公共的函数接口。_RunIt()为static函数,封装例行测试逻辑,给外界提供统一调用接口;Run() 只给了函数定义行,真正的定义,就是TEST之后的{}里,由用户自定义的那些代码。如1所说,TEST里可以直接调用base类里的成员。

3. 执行RegisterTest,#base,#name将变量名转换为字符串,注册类名和例行测试函数_RunIt。

bool TCONCAT(_Test_ignored_,name) =                                     \  ::leveldb::test::RegisterTest(#base, #name, &TCONCAT(_Test_,name)::_RunIt); 

这个函数的实际定义如下,将base,name,func放入一个全局的vector tests中

bool RegisterTest(const char* base, const char* name, void (*func)()) {  if (tests == NULL) {    tests = new std::vector<Test>;  }  Test t;  t.base = base;  t.name = name;  t.func = func;  tests->push_back(t);  return true;}

三。main函数的写法:执行所有测试。

int main(int argc, char** argv) {  return leveldb::test::RunAllTests();}

RunAllTest()的内部实现,就是将RegisterTest()注册过的函数调用一遍。

    for (size_t i = 0; i < tests->size(); i++) {      const Test& t = (*tests)[i];      (*t.func)();      .......      }

0 0
原创粉丝点击