audiopolicymanager_tests流程分析gtest测试程序基本流程

目录文件分析

audiopolicymanager_tests.cpp源码位于frameworks/av/services/audiopolicy/tests目录中;

该测试程序的目录树如下:

Andriod.mk为该测试程序的Makefile。

audiopolicymanager_tests.cpp为测试程序,主要使用gtest框架。

AudioPolicyTestClient.h定义了AudioPolicyClientInterface的派生类,作为Client用于AudioPolicy与AudioFlinger之间的通信。

AudioPolicyTestManager.h定义了AudioPolicyManager的派生类,主要用于管理AudioPolicy的事务。

分析audiopolicymanager_tests的gtest流程

文中使用了gtest框架中的两个测试接口来实现测试,分别是TEST与TEST_F。通过分析TEST的fixture_class是Test,而TEST_F的fixture_class则是继承于TEST的派生类。比如audiopolicymanager_tests的TEST_F指定的fixture_class是AudioPolicyManagerTest。

TEST分析

audiopolicymanager_tests.cpp代码如下:

TEST(AudioPolicyManagerTestInit, Failure) {
    AudioPolicyTestClient client;
    AudioPolicyTestManager manager(&client);
    manager.getConfig().setDefault();
    // Since the default client fails to open anything,
    // APM should indicate that the initialization didn't succeed.
    ASSERT_EQ(NO_INIT, manager.initialize());
    ASSERT_EQ(NO_INIT, manager.initCheck());
}

TEST在gtest中被指定为一个宏,该宏通过传入的参数,来在内部创建一个继承于using testing::Test派生类。下面简单分析该派生类的创建过程。

1. 在gtest/gtest.h中定义的TEST宏指向于GTEST_TEST_。

#define GTEST_TEST(test_suite_name, test_name)             \
  GTEST_TEST_(test_suite_name, test_name, ::testing::Test, \
              ::testing::internal::GetTestTypeId())

// Define this macro to 1 to omit the definition of TEST(), which
// is a generic name and clashes with some other libraries.
#if !GTEST_DONT_DEFINE_TEST
#define TEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name)
#endif

2. GTEST_TEST_宏定义在gtest-internal.h中,其中TestBody()的实现audiopolicymanager_tests.cpp的TEST后面定义。

// Expands to the name of the class that implements the given test.
#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
  test_suite_name##_##test_name##_Test

// Helper macro for defining tests.
#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id)      \
  static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1,                \
                "test_suite_name must not be empty");                         \
  static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1,                      \
                "test_name must not be empty");                               \
  class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)                    \
      : public parent_class {                                                 \
   public:                                                                    \
    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {}                   \
    ~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override = default; \
    GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name,   \
                                                           test_name));       \
    GTEST_DISALLOW_MOVE_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name,   \
                                                           test_name));       \
                                                                              \
   private:                                                                   \
    void TestBody() override;                                                 \
    static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;     \
  };                                                                          \
                                                                              \
  ::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()

3. 当类创建完之后,会初始化静态成员变量test_info_,最终通过调用::testing::internal::MakeAndRegisterTestInfo方法

创建一个TestInfo示例和一个TestSuite实例,并将新创建的TestSuite添加到internal::UnitTestImpl::test_suites_中,将TestInfo添加到TestSuite实例中。此处代码略。

TEST_F分析

1. 在gtest/gtest.h中定义的TEST_F宏指向于GTEST_TEST_。

#if !GTEST_DONT_DEFINE_TEST
#define TEST_F(test_fixture, test_name)\
  GTEST_TEST_(test_fixture, test_name, test_fixture, \
              ::testing::internal::GetTypeId<test_fixture>())
#endif  // !GTEST_DONT_DEFINE_TEST

2. 创建测试组件类的方法与TEST中的方法一样,都是通过调用::testing::internal::MakeAndRegisterTestInfo方法来实现的。只不过此创建的组件类父类不再是::testing::Test了,而是::testing::Test的派生类。

3. audiopolicymanager_tests.cpp文件中::testing::Test的派生类为AudioPolicyManagerTest。该测试类的定义如下:

class AudioPolicyManagerTest : public testing::Test {
  protected:
    virtual void SetUp();
    virtual void TearDown();

    std::unique_ptr<AudioPolicyManagerTestClient> mClient;
    std::unique_ptr<AudioPolicyTestManager> mManager;
};

该类实现了父类定义的SetUp和TearDown函数,这两个方法定义了该组件类在RUN_ALL_TESTS()时分别安装与卸载私有资源。例如:

void AudioPolicyManagerTest::SetUp() {
    mClient.reset(new AudioPolicyManagerTestClient);
    mManager.reset(new AudioPolicyTestManager(mClient.get()));
    mManager->getConfig().setDefault();
    ASSERT_EQ(NO_ERROR, mManager->initialize());
    ASSERT_EQ(NO_ERROR, mManager->initCheck());
}

void AudioPolicyManagerTest::TearDown() {
    mManager.reset();
    mClient.reset();
}

 

程序流程

通过在测试文件中定义TEST或者TEST_F功能块,在程序运行时创建TEST和TEST_F指定的测试类,程序会调用testing::InitGoogleTest(&argc, argv)来进行环境变量的初始化,最终执行RUN_ALL_TESTS()进行测试类的创建,接着调用上文指定的setup()函数进行配置,并执行测试类的TestBody()函数来进行测试,完成之后TearDown()来回收资源。

总结

通过分析TEST与TEST_F宏,有下面的总结:

  1. TEST或者TEST_F后面必须跟测试功能块,该测试功能块是最终的测试TestBody();
  2. 使用TEST_F需要定义测试组件类,该类必须继承于testing::Test类;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值