为了提高代码质量,在同事的帮助下学习了如何使用gtest进行单元测试
准备工作
1
首先从googlecode上下载gtest的源码(googlecode明年一月即将关闭不知道这个项目会何去何从呢)
解压后参考README文件进行编译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| GTEST_TARGET=googletest ./travis.sh GTEST_TARGET=googlemock ./travis.sh ```
此时目录下会生成一个build目录,代码的单元测试依赖的就是这个目录里的静态库文件
2 安装lcov
一般yum即可安装,如果不行的话,那就下载安装
这里不用编译,直接make install即可
```c wget http: tar xvf lcov-1.11.tar.gz cd lcov-1.11 make install
|
3 准备项目代码和Makefile
首先创建一个gtest的目录,后面单元测试的代码都放在这个目录里面
头文件
1 2 3 4 5 6 7 8 9 10 11 12 13
| [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链接冲突
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| [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中规中矩没啥好说的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| [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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| 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
|
1 2 3 4 5 6 7 8 9 10 11 12
| 这个文件是对刚才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文件夹下有示例代码,不再赘述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| [root@localhost.localdomain gtest_test]# cat gtest/gtest_hello.cc #include "gtest/gtest.h" #include "hello.h" #define private public #define protected public
#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)); }
|
生成可视化结果
1 2 3 4
| 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目录上一级)
1 2
| ./run_gtest.sh -d ./ -g /root/googletest -c hello ./run_gtest.sh -d ./ -g /root/googletest
|