protected函数如何单元测试
类的protected
函数相比public
函数,测试套件定义的对象无法直接访问,gtest
提供了一个宏FRIENT_TEST
,这个宏定义如下:
#define FRIEND_TEST(test_case_name, test_name) \
friend class test_case_name##_##test_name##_Test
可以见到其实现,主要是将测试用例名及测试名链接起来当成是被测类的友元类(gtest
在运行时会自动将每个用例生成一个类进行运行)。
继续使用前文 public函数如何单元测试 使用到的model
作为例子,此处增加一个protected
的成员方法Factorial
(该方法同样借用自gtest
官方示例):
class model
{
private:
device* _pdevice;
network* _pnetwork;
public:
model();
~model();
void printmodelinfo();
void printmodelverion();
void printmodeldeviceinfo();
void printmodeldeviceversion();
void printmodeldeviceserial();
void printallinfo();
bool showImg();
bool showData();
bool IsPrime(int n);
**protected:**
**int Factorial(int n);**
};
下面来看看protected
函数具体如何实施单元测试。
1.首先构建测试套件,定义一个继承自testing::Test
的类
class modelTest : public testing::Test {
protected:
};
2.同样需要复写SetUp/TearDown
两个函数
class modelTest : public testing::Test {
protected:
**void SetUp() override {**
**}**
**void TearDown() override {**
**}**
};
3.定义想要测试单元测试需要用到的数据,并在SetUp
进行初始化,在TearDown
中进行清理或析构。
class modelTest : public testing::Test {
protected:
void SetUp() override {
**pm = new model;**
}
void TearDown() override {
**if (pm) {**
**delete pm;**
**pm = NULL;**
**}**
}
**model* pm;**
};
4.通过TEST_F
宏定义想要测试的类的protected
函数的测试用例
// Tests factorial of negative numbers.
TEST_F(modelTest, Negative) {
// This test is named "Negative", and belongs to the "FactorialTest"
// test case.
EXPECT_EQ(1, pm->Factorial(-5));
EXPECT_EQ(1, pm->Factorial(-1));
EXPECT_GT(pm->Factorial(-10), 0);
}
// Tests factorial of 0.
TEST_F(modelTest, Zero) {
EXPECT_EQ(1, pm->Factorial(0));
}
// Tests factorial of positive numbers.
TEST_F(modelTest, Positive) {
EXPECT_EQ(1, pm->Factorial(1));
EXPECT_EQ(2, pm->Factorial(2));
EXPECT_EQ(6, pm->Factorial(3));
EXPECT_EQ(40320, pm->Factorial(8));
}
此时运行的话,系统会报错:
面对这个问题,第一,我们可以先尝试应用gtest
提供的宏FRIEND_TEST
:
首先,我们需要在被测类model
中,使用FRIEND_TEST
将我们需要使用到的testname
进行注册
class model
{
private:
device* _pdevice;
network* _pnetwork;
public:
model();
~model();
void printmodelinfo();
void printmodelverion();
void printmodeldeviceinfo();
void printmodeldeviceversion();
void printmodeldeviceserial();
void printallinfo();
bool showImg();
bool showData();
bool IsPrime(int n);
protected:
int Factorial(int n);
**FRIEND_TEST(modelTest, Negative);**
**FRIEND_TEST(modelTest, Zero);**
**FRIEND_TEST(modelTest, Positive);**
};
其次,我们需要将FRIEND_TEST
宏定义的头文件包含进来
#include "gtest/gtest_prod.h"
最后,运行测试用例,成功运行
但是由于需要改动到非测试的源码,而我们工程源码中不一定有包含到gtest
相关的内容,很有可能会导致源工程编译出错,所以我们可以在*.pro
文件中,增加一个宏定义
DEFINES += UT
然后再在被测试类model
中,对新增的FRIEND_TEST
及其头文件,可以使用预编译处理
#ifdef UT
#include "gtest/gtest_prod.h"
#endif // UT
#ifdef UT
FRIEND_TEST(modelTest, Negative);
FRIEND_TEST(modelTest, Zero);
FRIEND_TEST(modelTest, Positive);
#endif // UT
这样就可以使得源工程编译不受单元测试新增处理的影响。
但是
这里要说但是了……这样的测试会改动到我们的源码,是侵入式的,很令人不爽。所以这里可以使用一种更取巧的方式:
#ifdef UT
#define protected public
#define private public
#endif // UT
简单、直接、粗暴……但有效,而且修改不影响到原有类,可以统一在某个都引用到的头文件中,那么一次添加,后人乘凉啊
对应的demo源码,请点击 protectedFunc
也可扫码关注博主同名公众号"不解之榬",回复 “protected” 获取