类的protected函数相比public函数,测试套件定义的对象无法直接访问,gtest提供了一个宏FRIENT_TEST,这个宏定义如下:
#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test
可以见到其实现,主要是将测试用例名及测试名链接起来当成是被测类的友元类[gtest在运行时会自动将每个用例生成一个类进行运行]。
继续使用前文使用到的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);
};
下面来看看具体如何实施。
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文件中,增加一个宏定义
然后再在被测试类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