gtest基础使用10:Google Test自带示例七:通过TestWithParam进行接口测试

一、环境信息

  1. Visual Studio 2019
  2. Windows 10
  3. 前导知识:Google Test自带示例六的学习总结

二、Google Test Sample07

1. 示例概述

1.1 示例7讲解了如何通过类testing::TestWithParm测试接口。待测试的接口还是PrimeTable.h(和示例6一样)

class PrimeTable 
{
    public:
        virtual bool IsPrime(int n) const = 0; 
        virtual int GetNextPrime(int p) const = 0;
        virtual ~PrimeTable() {}
};
class OnTheFlyPrimeTable : public PrimeTable{//接口的具体实现};
class PreCalculatedPrimeTable : public PrimeTable{//接口的具体实现};

2. TestWithParm介绍

2.1 类testing::TestWithParm的基础使用如下例所示,共分为三步:
(1) 定义test fixture:test fixture 继承自 类testing::TestWithParam,继承时需要注明参数类型,示例中是整形
(2) 使用宏TEST_P编写具体的测试用例:TEST_P(TestFixtureName,TestCaseName)
(3) 使用INSTANTIATE_TEST_CASE_P(TestSuiteName,TestFixtureName,Values)明确待使用的参数

class Instance2 : public testing::TestWithParam<int> {};
TEST_P(Instance2, basicTest)
{
    int n;
    n = GetParam();
    EXPECT_TRUE(n);
}
INSTANTIATE_TEST_CASE_P(ParamBasicTest, Instance2, testing::Values(1, -1, -2, 2));

在这里插入图片描述
2.2 对于GetParam( )函数,它可以定义在test fixture中、也可以定义在TEST_P中。GetParam( )从 ==testing::Values( )==中获取数据,数据类型和test fixture定义时的类型务必一致:示例中是整型
2.3 testing::TestWithParm 与 typed tests ,type-parameterized tests的对比
(1) 都可以用来进行接口测试
(2) typed tests 适用于 接口的实施例已明确的情况,它的使用步骤概括如下:
—首先定义test fixture(继承自类testing::Test 或 其他test fixture)
—其次定义types(即接口的所有实施例);
—然后使用宏 TYPED_TEST_CASE(TestFixtureName,types);明确要使用的test fixture和types
—最后,使用宏TYPED_TEST(TestCaseName, TestName) 编写具体的测试用例。 用例执行的时候,Google Test 会根据TYPED_TEST_CASE中定义的types,重复执行 TYPED_TEST中定义的用例
(3) type-parameterized tests 适用于 接口的实施例不明确的情况(接口仅仅定义,但是不知道具体的实施例),它的使用步骤概括如下:
—首先定义test fixture(继承自类testing::Test 或 其他test fixture)
—其次使用宏 TYPED_TEST_CASE_P(TestFixture) 明确待使用的test fixture
—第三步使用宏TYPED_TEST_P(TestFixture,TestCaseName*)编写测试用例
—第四步通过 REGISTER_TYPED_TEST_SUITE_P(TestFixture,TestCaseName1,TestCaseName2,…) 枚举上面的测试用例
综上, type-parameterized tests 的定义就完成了,它一般会打包为一个头文件,供接口实现者调用。调用方法如下

typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable> types //定义types
INSTANTIATE_TYPED_TEST_CASE_P(OnTheFlyAndPreCalculated, PrimeTableTest2, types);

3. 对应的单元测试用例

3.1 示例中用到了函数指针,导致代码的阅读难度还是蛮大的
3.2 详细注释请参考下面的代码
3.3 用例执行结果如下
在这里插入图片描述

#include "pch.h"

// 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.
// 示例演示了如何使用 value-parameterized tests 测试一个接口的多个实施例
// 测试用例中的每一条测试都有一个参数,这个参数是一个接口指针、指向待测试的实施例

// The interface and its implementations are in this header.
#include "PrimeTable.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.
    // 需要避免测试用例之间的互相影响,比如1#用例改变了预置条件中的测试资源,导致2#用例执行失败
    // 我们需要保障每一条测试用例所使用的测试资源是一致的,在sample07中,我们通过Test fixture中SetUp()创造测试资源、TearDown()删除测试资源
    
    typedef PrimeTable* CreatePrimeTableFunc(); //将CreatePrimeTableFunc()函数 定义为 返回一个指向PrimeTable类的指针

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

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

    // 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.
    // 可以通过 GetParam( ) 获取待测试的参数,GetParam( )可以定义在测试用例中,也可以定义在test fixture中的SetUp()和TearDown()
    // 在示例中,test parameter是一个factory function(函数地址?),供我们在SetUp( )中创建和存储接口的实施例
    class PrimeTableTest : public TestWithParam< CreatePrimeTableFunc*> 
    { //CreatePrimeTableFunc*是函数地址(函数地址=函数指针)? 这种使用方法之前没见过
    protected:
        PrimeTable* table_;
    public:
        void SetUp() override 
        { 
            table_ = ( * GetParam() )(); //GetParam()从Values()中获取数据,本示例获取的是函数地址(函数指针),先加*表示为具体函数、后面跟()表示执行
            
            //Values( &CreateOnTheFlyPrimeTable, &CreatePreCalculatedPrimeTable<1000> ) //函数指针赋值要使用 &
            //table_ = (*GetParam())(); 相当于 table_ = CreateOnTheFlyPrimeTable();  +  table_ = CreatePreCalculatedPrimeTable<1000>();
        } 

        void TearDown() override
        {
            delete table_;
            table_ = nullptr;
        }

        ~PrimeTableTest() override { delete table_; }
        
    };

    TEST_P(PrimeTableTest, 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(PrimeTableTest, 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(PrimeTableTest, 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.
    // 为了运行 value-parameterized tests,你需要实例化他们 或者 将他们绑定至一个列表(这个列表中的值将作为test parameters被使用)。
    // 他们=value-parameterized tests
    
    // Here, we instantiate our tests with a list of two PrimeTable object factory functions:
    // 下面,通过列表实例化测试(这个列表包含两个PrimeTable对象)
    INSTANTIATE_TEST_CASE_P( TestSuitName, PrimeTableTest, Values( &CreateOnTheFlyPrimeTable, &CreatePreCalculatedPrimeTable<1000> ) );
    //INSTANTIATE_TEST_SUITE_P(TestCaseName,TestFixtureName,Values). For VS2019, use INSTANTIATE_TEST_CASE_P. //函数指针赋值要使用&
}  // namespace

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值