googletest:sample7分析

目录

googletest:sample1
googletest:sample2
googletest:sample3
googletest:sample4
googletest:sample5
googletest:sample6
googletest:sample7
googletest:sample8
googletest:sample9

待测文件

sample6,都是prime_tables.h文件

PrimeTable类声明了素数表的一系列接口,包括
1)IsPrime:判断当前输入数n是否为素数;
2)GetNextPrime:找比输入数n大的下一个素数.

文件内容略.

测试文件

sample6的测试,类型参数化测试,利用"typed test" "type-parameterized tests" 2种方法复用test,对不同类型的派生类进行测试.

sample7的测试,接口测试,利用"value-parameterized tests" 复用test,测试接口的多个实现的公共属性.

步骤:
1)利用工厂方法CreateOnTheFlyPrimeTable, CreatePreCalculatedPrimeTable创建待测对象;
2)利用夹具类的Setup(),TearDown()负责待测对象的创建、销毁;
3)利用TEST_P()定义test;
4)利用INSTANTIATE_TEST_SUITE_P初始化作为测试参数的值列表.


tips: TEST_P(test_suite_name, test_name)定义一个test,test_suite_name必须匹配测试夹具名,test_name是自定义test名称.


// This sample shows how to test common properties of multiple
// implementations of an interface (aka interface tests) using
// value-parameterized tests. Each test in the test case has
// a parameter that is an interface pointer to an implementation
// tested.

// The interface and its implementations are in this header.
#include "prime_tables.h"
#include "gtest/gtest.h"
namespace {

using ::testing::TestWithParam;
using ::testing::Values;

// As a general rule, to prevent a test from affecting the tests that come
// after it, you should create and destroy the tested objects for each test
// instead of reusing them.  In this sample we will define a simple factory
// function for PrimeTable objects.  We will instantiate objects in test's
// SetUp() method and delete them in TearDown() method.
typedef PrimeTable* CreatePrimeTableFunc();

PrimeTable* CreateOnTheFlyPrimeTable() { return new OnTheFlyPrimeTable(); }

template <size_t max_precalculated>
PrimeTable* CreatePreCalculatedPrimeTable() {
  return new PreCalculatedPrimeTable(max_precalculated);
}

// Inside the test body, fixture constructor, SetUp(), and TearDown() you
// can refer to the test parameter by GetParam().  In this case, the test
// parameter is a factory function which we call in fixture's SetUp() to
// create and store an instance of PrimeTable.
class PrimeTableTestSmpl7 : public TestWithParam<CreatePrimeTableFunc*> {
 public:
  ~PrimeTableTestSmpl7() override { delete table_; }
  void SetUp() override { table_ = (*GetParam())(); }
  void TearDown() override {
    delete table_;
    table_ = nullptr;
  }

 protected:
  PrimeTable* table_;
};

TEST_P(PrimeTableTestSmpl7, ReturnsFalseForNonPrimes) {
  EXPECT_FALSE(table_->IsPrime(-5));
  EXPECT_FALSE(table_->IsPrime(0));
  EXPECT_FALSE(table_->IsPrime(1));
  EXPECT_FALSE(table_->IsPrime(4));
  EXPECT_FALSE(table_->IsPrime(6));
  EXPECT_FALSE(table_->IsPrime(100));
}

TEST_P(PrimeTableTestSmpl7, ReturnsTrueForPrimes) {
  EXPECT_TRUE(table_->IsPrime(2));
  EXPECT_TRUE(table_->IsPrime(3));
  EXPECT_TRUE(table_->IsPrime(5));
  EXPECT_TRUE(table_->IsPrime(7));
  EXPECT_TRUE(table_->IsPrime(11));
  EXPECT_TRUE(table_->IsPrime(131));
}

TEST_P(PrimeTableTestSmpl7, CanGetNextPrime) {
  EXPECT_EQ(2, table_->GetNextPrime(0));
  EXPECT_EQ(3, table_->GetNextPrime(2));
  EXPECT_EQ(5, table_->GetNextPrime(3));
  EXPECT_EQ(7, table_->GetNextPrime(5));
  EXPECT_EQ(11, table_->GetNextPrime(7));
  EXPECT_EQ(131, table_->GetNextPrime(128));
}

// In order to run value-parameterized tests, you need to instantiate them,
// or bind them to a list of values which will be used as test parameters.
// You can instantiate them in a different translation module, or even
// instantiate them several times.
//
// Here, we instantiate our tests with a list of two PrimeTable object
// factory functions:
INSTANTIATE_TEST_SUITE_P(OnTheFlyAndPreCalculated, PrimeTableTestSmpl7,
                         Values(&CreateOnTheFlyPrimeTable,
                                &CreatePreCalculatedPrimeTable<1000>));

}  // namespace

用宏INSTANTIATE_TEST_SUITE_P + Values 实例化包含一个包含2个PrimeTable对象工厂方法的列表,GTest就会进行value-parameterized tests,为每个参数实例化test;

INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...)实例化一个test suite,"prefix"是test_suite_name的前缀名,"test_suite_name"是组件名,"..."包含了要用作test parameters的值列表.

而在Test, Test Fixture的ctor, Setup(), TearDown()中,可通过GetParam()获取列表中的参数.

小结

3个宏TEST, TEST_F, TEST_P, TYPED_TEST区别:

  • TEST

用于创建最简单的test,定义一个测试函数,在其中可定义任何C++代码并用gtest提供的断言进行检查. 不需要继承任何类.

语法:

TEST(test_suite_name, test_name)

其中,test_suite_name 测试组件名,test_name 测试名.

示例:sample1, sample2, sample4

  • TEST_F

用于创建需要共享测试对象的test,需要搭配自定义test fixture(测试夹具,继承自testing::Test)类使用,用virtual Setup(), TearDown()管理测试对象执行test前的初始化、执行后的清理工作.

TEST_F(test_fixture, test_name)

其中,test_fixture 测试夹具名,test_name 测试名.

示例:sample3, sample5

  • TEST_P

用于参数化test. 允许开发者为同一个test提供多个参数,自动为每个参数生成一个单独的test. 通过INSTANTIATE_TEST_SUITE_P指定数据集,GTest自动为每个数据在运行时生成相应的test并执行.

TEST_P(test_suite_name, test_name)

其中,test_suite_name 测试组件名,需匹配测试夹具名,test_name测试名.

示例:sample7

  • TYPED_TEST

用于类型化test,针对多种类型需要复用同一test的情形. 基于C++模板实现.

TYPED_TEST(CaseName, TestName)

其中,CaseName 用例名,需要匹配测试夹具名,TestName 测试名.

示例:sample6

参考

gtest中TEST和TEST_F和TEST_P的区别是什么

【C++ 单元测试】 GTest 指南:剖析 TEST_P 与 TYPED_TEST

posted @ 2025-03-01 12:10  明明1109  阅读(38)  评论(0)    收藏  举报