levelDB源码笔记(1)-TEST

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值