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_fixture>())
以TEST_F(QueueTest, IsEmptyInitially)为例,test_fixture就是QueueTest; test_name 就是IsEmptyInitially; ::testing::internal::GetTypeId<test_fixture>()表示返回test_fixture类型的ID号。所以TEST_F(QueueTest, IsEmptyInitially)经过预处理就替换为 GTEST_TEST_(QueueTest,IsEmptyInitially,QueueTest,::testing::internal::GetTypeId<QueueTest>())。
#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<GTEST_TEST_CLASS_NAME_( \
test_suite_name, test_name)>); \
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<QueueTest>::GetSetUpCaseOrSuite(__FILE__, __LINE__),
::testing::internal::SuiteApiResolver<QueueTest>::GetTearDownCaseOrSuite(__FILE__, __LINE__),
new ::testing::internal::TestFactoryImpl<QueueTest_IsEmptyInitially_Test>
);
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>看名字就知道是个工厂对象,用来创建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<int>(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<int>(test_indices_.size()));
}
到这里TEST_F的工作就完成了,总结起来就完成了三件事
- 创建新的test类
- 查找根据test suite名字查找test suite对象,没有找到就创建新的test suite
- 注册新的test info