macro trick in googletest

Posted on

googletestでは、テストケースはこう書くわけ。

1
2
3
4
5
#include <gtest/gtest.h>

TEST(SampleTestCase, TestFunc) {
    EXPECT_TRUE(true);
}

C++な割にはスマート。で、なんで、こんなことができるのか。その仕組みを追ってみた。まずは TEST() マクロ。

include/gtest/gtest.h:

1
2
3
4
#define TEST(test_case_name, test_name) \
  GTEST_TEST_(test_case_name, test_name, \
              ::testing::Test,\
              ::testing::internal::GetTestTypeId())

ほむ。次は GTEST_TEST_() マクロ。

include/gtest/internal/gtest-internal.h(抜粋):

1
2
3
4
5
6
7
8
9
#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
 public:\
  GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
 private:\
  virtual void TestBody();\
};\
\
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()

ほむほむ。GTEST_TEST_CLASS_NAME_()マクロは、test_case_nameとtest_nameを繋げて重複しないクラス名を生成する。上の例だと SampleTestCase_TestFunc_Test となる。最後の行は TestBody() のシグニチャだけ置いて、マクロに続くブロックが TestBody() の実装となるようになっているわけだ。

ちなみに、親クラスとなる ::testing::Test は include/gtest/gtest.h で定義されている。

include/gtest/gtest.h(抜粋):

1
2
3
4
5
6
7
class Test {
 protected:
  virtual void SetUp();
  virtual void TearDown();
 private:
  virtual void TestBody() = 0;
};

ほむほむほむ。予想どおり。

まとめ

最後に始めに出した例と、展開されたあとのイメージを載せておく。

展開前:

1
2
3
TEST(SampleTestCase, TestFunc) {
    EXPECT_TRUE(true);
}

展開後:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class SampleTestCase_TestFunc_Test : public ::testing::Test {
 public:
  SampleTestCase_TestFunc_Test() {}
 private:
  virtual void TestBody();
};

void SampleTestCase_TestFunc_Test::TestBody() {
    EXPECT_TRUE(true);
}

なるほどねぇ。