前言:根据网上满山遍野的gtest介绍,再结合自己的项目经验,做一下个人总结。

1.应用场景

gtest是google的一款代码检查工具,功能确实很强大,但也要看用在什么地方了。

a.对一个不太成熟的模块,需要gtest,因为gtest可以检测参数值和逻辑是否达到预期;

b.对一个刚刚解耦合的系统,需要gtest,以检测各个模块是否协同工作。

c.大忌:如果对一个本来就很成熟的模块,还要去添加gtest,就很画蛇添足,把原本稳定的逻辑弄得非常混乱,耗时耗力,得不偿失。

如果非得添加的话,就在模块的入口,重要节点添加gtest就可以了,gtest用好了,是把利剑;用不好,就是一坨shi。

2.个人见解

a.gtest其实最主要,也是最核心的是gmock,当一个系统比较复杂时,然后你要测某一个模块的逻辑,那么就把这个模块所依赖的模块和库进行抽象,或者说是模拟,通过模拟传参,传对象,让这个模块正常运行,从而查看程序是否达到预期。

b.gmock的原理,实质就是用了c++的多态,而多态是需要该接口为虚函数,那么就存在这么一个尴尬的场景,源代码没有虚函数,而接口里面又依赖其他模块,我想这是很多模块最常见的场景了,因为刚开始设计时,并没有考虑gtest,所以才会这样。(如果是虚函数,可以直接MOCK_METHOD)

解决方案:

创建一个代理类,通过代理类来创建虚函数,代码如下:

#define GTEST_XXX
#ifdef GTEST_XXX
public:
    class agentClass 
    {
        public:
        virtual int getTestValue(int & testValue);
        virtual ~agentClass() {};
    }

    void setMock(agentClass * func)
    {
        g_func = func;
    }
private:
    agentClass * g_func;
#endif

class mockClass : public agentClass 
{
public:
    virtual ~mockClass() {};
    MOCK_METHOD1(getTestValue, int(int &));
}

TEST_F(testClass, getTestValue)
{
    mockClass mockClassTest;
    g_xx.setMock(&mockClassTest);

    int i = 0;
    g_xx.getTestValue(i);
}

c.项目中的实际情况,并不是单纯的独立的模块依赖,而是因为场景的复杂性,很多模块都交织在一起,需要满足很多模块的运行条件;同时完成一个动作,也需要很多模块同时支持。

所以在写gtest时,可以尝试把这些模块统一打包成一个接口,然后进行gmock,不然对每一个模块进行gmock,真的会让人头皮发麻!!!

d.由于程序是层次调用的关系,并不需要所有接口都需要gtest,而是抓住牛鼻子,通过EXPECT_ALL进行设置参数,让程序有种指哪打哪的感觉,这样程序就很健壮,逻辑清晰,移植方便,可复用性强。

e.对于一个类,可以将类接口,在一个TEST_F里面实现,没必要写很多个TEST_F;或者TEST_F去测试某一段逻辑;或者TEST_F去测试某一个动作/操作;或者TEST_F去测试某一个流程,比如注册,开始,等待,结束这样的流程,我给它取名叫TEST_F集合