google test之TEST_F解析

TEST_F是用来创建test fixtures测试,来看看TEST_F是如何创建 test fixtures测试的。

#define TEST_F(test_fixture, test_name)\
                          GTEST_TEST_(test_fixture, test_name, test_fixture, \
                           ::testing::internal::GetTypeId())

以TEST_F(QueueTest, IsEmptyInitially)为例,test_fixture就是QueueTest; test_name 就是IsEmptyInitially; ::testing::internal::GetTypeId()表示返回test_fixture类型的ID号。所以TEST_F(QueueTest, IsEmptyInitially)经过预处理就替换为 GTEST_TEST_(QueueTest,IsEmptyInitially,QueueTest,::testing::internal::GetTypeId())。

#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id)      \
  class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)                    \
      : public parent_class {                                                 \
   public:                                                                    \
    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {}                   \
                                                                              \
   private:                                                                   \
    virtual void TestBody();                                                  \
    static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;     \
    GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name,   \
                                                           test_name));       \
  };                                                                          \
                                                                              \
  ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name,          \
                                                    test_name)::test_info_ =  \
      ::testing::internal::MakeAndRegisterTestInfo(                           \
          #test_suite_name, #test_name, nullptr, nullptr,                     \
          ::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \
          ::testing::internal::SuiteApiResolver<                              \
              parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__),         \
          ::testing::internal::SuiteApiResolver<                              \
              parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__),      \
          new ::testing::internal::TestFactoryImpl);                                  \
  void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()

上面是GTEST_TEST_展开的样子,那么TEST_F(QueueTest, IsEmptyInitially)最终展开后如下

class QueueTest_IsEmptyInitially_Test  :public QueueTest{
public:                                                                    
   QueueTest_IsEmptyInitially_Test(test_suite_name, test_name)() {} 
private:
   virtual void TestBody();
   static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;
   GTEST_DISALLOW_COPY_AND_ASSIGN_( QueueTest_IsEmptyInitially_Test);
};
::testing::TestInfo* const QueueTest_IsEmptyInitially_Test::test_info_ =
::testing::internal::MakeAndRegisterTestInfo(
"QueueTest_IsEmptyInitially_Test", 
"QueueTest", 
nullptr,
nullptr,
::testing::internal::CodeLocation(__FILE__, __LINE__), 
(parent_id),
::testing::internal::SuiteApiResolver::GetSetUpCaseOrSuite(__FILE__, __LINE__),
::testing::internal::SuiteApiResolver::GetTearDownCaseOrSuite(__FILE__, __LINE__),
 new ::testing::internal::TestFactoryImpl
);
void QueueTest_IsEmptyInitially_Test::TestBody()
{
    EXPECT_EQ(q0_.size(), 0);
}

看了上面的代码之后,前面的讲解就更加直观明了了,TEST_F(QueueTest, IsEmptyInitially)会声明一个类,类名字是由TestSuite和Test的组合,而且声明的这个类继承名字为TestSuite的类。TEST_F定义的函数体就变成了新类中TestBody()的函数体。
test fixtures类是创建了,类要被使用就需要实例化。test fixtures类的对象在哪里创建呢?接着看test fixtures类,还有个成员test_info_,它又是被MakeAndRegisterTestInfo赋值,MakeAndRegisterTestInfo有个参数new ::testing::internal::TestFactoryImpl看名字就知道是个工厂对象,用来创建QueueTest_IsEmptyInitially_Test。看看MakeAndRegisterTestInfo的实现

namespace internal {

// Creates a new TestInfo object and registers it with Google Test;
// returns the created object.
//
// Arguments:
//
//   test_suite_name:   name of the test suite
//   name:             name of the test
//   type_param:       the name of the test's type parameter, or NULL if
//                     this is not a typed or a type-parameterized test.
//   value_param:      text representation of the test's value parameter,
//                     or NULL if this is not a value-parameterized test.
//   code_location:    code location where the test is defined
//   fixture_class_id: ID of the test fixture class
//   set_up_tc:        pointer to the function that sets up the test suite
//   tear_down_tc:     pointer to the function that tears down the test suite
//   factory:          pointer to the factory that creates a test object.
//                     The newly created TestInfo instance will assume
//                     ownership of the factory object.
TestInfo* MakeAndRegisterTestInfo(
    const char* test_suite_name, const char* name, const char* type_param,
    const char* value_param, CodeLocation code_location,
    TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
    TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) {
  TestInfo* const test_info =
      new TestInfo(test_suite_name, name, type_param, value_param,
                   code_location, fixture_class_id, factory);
  GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
  return test_info;
}

MakeAndRegisterTestInfo中创建了TestInfo对象并将其注册到google test中去。将TestInfo对象注册到google test中去吗?接着往下看

 // Adds a TestInfo to the unit test.
  //
  // Arguments:
  //
  //   set_up_tc:    pointer to the function that sets up the test suite
  //   tear_down_tc: pointer to the function that tears down the test suite
  //   test_info:    the TestInfo object
  void AddTestInfo(internal::SetUpTestSuiteFunc set_up_tc,
                   internal::TearDownTestSuiteFunc tear_down_tc,
                   TestInfo* test_info) {
    // In order to support thread-safe death tests, we need to
    // remember the original working directory when the test program
    // was first invoked.  We cannot do this in RUN_ALL_TESTS(), as
    // the user may have changed the current directory before calling
    // RUN_ALL_TESTS().  Therefore we capture the current directory in
    // AddTestInfo(), which is called to register a TEST or TEST_F
    // before main() is reached.
    if (original_working_dir_.IsEmpty()) {
      original_working_dir_.Set(FilePath::GetCurrentDir());
      GTEST_CHECK_(!original_working_dir_.IsEmpty())
          << "Failed to get the current working directory.";
    }

    GetTestSuite(test_info->test_suite_name(), test_info->type_param(),
                 set_up_tc, tear_down_tc)
        ->AddTestInfo(test_info);
  }

GetTestSuite查找名字为test_info->test_suite_name()的test suite对象,如果没有发现就创建新的test suite,并添加到test suite集合中去。最后返回test suite。

// Finds and returns a TestSuite with the given name.  If one doesn't
// exist, creates one and returns it.  It's the CALLER'S
// RESPONSIBILITY to ensure that this function is only called WHEN THE
// TESTS ARE NOT SHUFFLED.
//
// Arguments:
//
//   test_suite_name: name of the test suite
//   type_param:     the name of the test suite's type parameter, or NULL if
//                   this is not a typed or a type-parameterized test suite.
//   set_up_tc:      pointer to the function that sets up the test suite
//   tear_down_tc:   pointer to the function that tears down the test suite
TestSuite* UnitTestImpl::GetTestSuite(
    const char* test_suite_name, const char* type_param,
    internal::SetUpTestSuiteFunc set_up_tc,
    internal::TearDownTestSuiteFunc tear_down_tc) {
  // Can we find a TestSuite with the given name?
  const auto test_suite =
      std::find_if(test_suites_.rbegin(), test_suites_.rend(),
                   TestSuiteNameIs(test_suite_name));

  if (test_suite != test_suites_.rend()) return *test_suite;

  // No.  Let's create one.
  auto* const new_test_suite =
      new TestSuite(test_suite_name, type_param, set_up_tc, tear_down_tc);

  // Is this a death test suite?
  if (internal::UnitTestOptions::MatchesFilter(test_suite_name,
                                               kDeathTestSuiteFilter)) {
    // Yes.  Inserts the test suite after the last death test suite
    // defined so far.  This only works when the test suites haven't
    // been shuffled.  Otherwise we may end up running a death test
    // after a non-death test.
    ++last_death_test_suite_;
    test_suites_.insert(test_suites_.begin() + last_death_test_suite_,
                        new_test_suite);
  } else {
    // No.  Appends to the end of the list.
    test_suites_.push_back(new_test_suite);
  }

  test_suite_indices_.push_back(static_cast(test_suite_indices_.size()));
  return new_test_suite;
}

AddTestInfo 将会将test info对象添加到 test info集test_info_list_中去。在真正运行test时会根据test info信息创建对应的test 对象。

// Adds a test to this test suite.  Will delete the test upon
// destruction of the TestSuite object.
void TestSuite::AddTestInfo(TestInfo* test_info) {
  test_info_list_.push_back(test_info);
  test_indices_.push_back(static_cast(test_indices_.size()));
}

到这里TEST_F的工作就完成了,总结起来就完成了三件事

  • 创建新的test类
  • 查找根据test suite名字查找test suite对象,没有找到就创建新的test suite
  • 注册新的test info

你可能感兴趣的:(google test之TEST_F解析)