gtest使用说明

原创内容,转载请注明出处

Posted by Weakyon Blog on September 16, 2015

为了提高代码质量,在同事的帮助下学习了如何使用gtest进行单元测试

准备工作

1 首先从googlecode上下载gtest的源码(googlecode明年一月即将关闭不知道这个项目会何去何从呢)

解压后参考README文件进行编译

  
GTEST_TARGET=googletest ./travis.sh
GTEST_TARGET=googlemock ./travis.sh

此时目录下会生成一个build目录,代码的单元测试依赖的就是这个目录里的静态库文件

2 安装lcov

一般yum即可安装,如果不行的话,那就下载安装

这里不用编译,直接make install即可

  
wget http://downloads.sourceforge.net/ltp/lcov-1.11.tar.gz
tar xvf lcov-1.11.tar.gz
cd lcov-1.11
make install

3 准备项目代码和Makefile

首先创建一个gtest的目录,后面单元测试的代码都放在这个目录里面

头文件

  
[root@localhost.localdomain gtest_test]# cat hello.h 
#ifndef HELLO_H
#define HELLO_H

class hello{
public:
        hello();
        int set_i(int temp);
private:
        int i;
};

#endif

CPP文件

注意这里只要使用到main函数,外部一定要加上ifndef GOOGLE_TEST否则后面的操作会报错,main链接冲突

  
[root@localhost.localdomain gtest_test]# cat hello.cpp 
#include "hello.h"
#include <iostream>

using namespace std;

hello::hello()
{
        i = 0;
}

int hello::set_i(int temp)
{
        i = temp;
        return i;
}

#ifndef GOOGLE_TEST
int main()
{
        class hello A;
        cout << A.set_i(1) << endl;
}
#endif

项目本身的Makefile中规中矩没啥好说的

[root@localhost.localdomain gtest_test]# cat Makefile 
CC=g++
CFLAGS=-std=c++0x -g -O2 -Wall -Wno-deprecated 
INCLUDE=-I./
LINK_LIBS=-L./
TARGET=hello
OBJS=$(patsubst %.cpp,%.o,$(wildcard *.cpp))
OBJS+=$(patsubst %.cc,%.o,$(wildcard *.cc))

all:$(TARGET)

$(TARGET):$(OBJS)
        @echo "  LD    $@"
        @$(CC) -o $@ $^ $(LINK_LIBS)

.cpp.o:
        @echo "  CC    $@"
        @$(CC) $(CFLAGS) -o $@ -c $< $(INCLUDE)

.cc.o:
        @echo "  CC    $@"
        @$(CC) $(CFLAGS) -o $@ -c $< $(INCLUDE)

clean:
        rm -f $(TARGET) $(OBJS)

然后是gtest的Makefile

CC=g++                                                                                        
GTEST_DIR=/root/googletest
CFLAGS=-fprofile-arcs -ftest-coverage -DGOOGLE_TEST -std=c++0x -g -O2 -Wall -Wno-deprecated   
INCLUDE=-I$(GTEST_DIR)/googletest/include -I./                                           
LINK_LIBS=$(GTEST_DIR)/build/googletest/libgtest.a -lpthread -fprofile-arcs -ftest-coverage -L./
TARGET=gtests
OBJS=$(patsubst %.cpp,%.o,$(wildcard *.cpp))                                                  
OBJS+=$(GTEST_DIR)/googletest/src/gtest_main.o                                                
OBJS+=$(patsubst %.cc,%.o,$(wildcard gtest/*.cc))                                             
OBJS+=$(patsubst %.cc,%.o,$(wildcard *.cc))                                                   

all:$(TARGET)
                                                                                              
$(TARGET):$(OBJS)                                                                             
        @echo "  LD    $@"                                                                    
        @$(CC) -o $@ $^ $(LINK_LIBS)
                                                                                              
.cpp.o:                                                                                       
        @echo "  CC    $@"                                                                    
        @$(CC) $(CFLAGS) -o $@ -c $< $(INCLUDE)                                               
                                                                                              
.cc.o:                                                                                        
        @echo "  CC    $@"
        @$(CC) $(CFLAGS) -o $@ -c $< $(INCLUDE)

clean:
        rm -f $(TARGET) $(OBJS)
.cleanall: 
        rm -f $(TARGET) $(OBJS) 
        rm -rf *.gcno *.gcda gtest/*.gcno gtest/*.gcda gtest/app.info gtest/results 
这个文件是对刚才hello项目的文件修改而生成的
GTEST_DIR路径是刚才编译完的build路径的上一级
CFLAGS需要加上-fprofile-arcs -ftest-coverage -DGOOGLE_TEST
INCLUDE需要加上-I$(GTEST_DIR)/googletest/include
LINK_LIBS需要加上$(GTEST_DIR)/build/googletest/libgtest.a -lpthread -fprofile-arcs -ftest-coverage -lpthread
TARGET修改为gtests
加上一句OBJS+=$(GTEST_DIR)/googletest/src/gtest_main.o
和OBJS+=$(patsubst %.cc,%.o,$(wildcard gtest/*.cc))
另外加上一段来清除运行gtest生成的中间文件
.cleanall: 
        rm -f $(TARGET) $(OBJS) 
        rm -rf *.gcno *.gcda gtest/*.gcno gtest/*.gcda gtest/app.info gtest/results

编写单元测试代码

单元测试代码如何写,在samples文件夹下有示例代码,不再赘述

[root@localhost.localdomain gtest_test]# cat gtest/gtest_hello.cc 
#include "gtest/gtest.h"
#include "hello.h"
#define private public
#define protected public
//add header file of tested object here...
#undef private
#undef protected
class TS_hello : public testing::Test {
    protected:
        static void SetUpTestCase() {}
        static void TearDownTestCase() {}
        virtual void SetUp() {}
        virtual void TearDown() {}
};

TEST_F (TS_hello, main) {
        class hello A;
        ASSERT_EQ(1,A.set_i(1));
}

生成可视化结果

make
./gtests
lcov --directory ./ --capture --output-file ./gtest/app.info
genhtml -o ./gtest/results ./gtest/app.info

此时运行结果就在gtest/results/index.html下了,这是个可以直接打开的网页

示例图

福利脚本

我同事做了个shell脚本,利用这个脚本能够很轻松的生成结果,也贴在这里

福利脚本

d选项是项目路径

c选项是生成单元测试代码模版,例如hello就是生成gtest_hello.cc,不加这个选项就能自动生成可视化分析页面

g选项是指定gtest代码路径(build目录上一级)

./run_gtest.sh -d ./ -g /root/googletest -c hello
./run_gtest.sh -d ./ -g /root/googletest
16 Sep 2015