zoukankan      html  css  js  c++  java
  • C++测试利器--google test开源测试框架

    资料

      偶然发现了google的测试框架gtest,马上试了下,效果挺不错,特别是对于写c++的人来说,方便很多。以前自己写c++的模块,通常是写好了模块后再另外定义些函数,然后在函数里面写测试用例来测试模块,如果测试点比较多,光是定义测试函数都要花费不少时间。gtest相当于大大节省了这个过程,用起来非常简单,直接用宏来定义测试用例,并且有很多丰富的宏来辅助测试,例如断言、预测值、死亡测试等。

      废话不多说,先上gtest的一些资料:

    gtest的代码托管地址:https://github.com/google/googletest,用git clone下来就可以了。

    使用gtest构建测试用例指导:https://github.com/google/googletest/tree/master/googletest

    gtest英文文档:https://github.com/google/googletest/blob/master/googletest/docs/Documentation.md

    gtest中文博客:玩转Google开源C++单元测试框架Google Test系列,这系列博客对gtest的具体使用讲解的非常详细。

    gmock使用文档:https://github.com/google/googletest/blob/master/googlemock/docs/Documentation.md

    gmock中文文档:Google Mock启蒙篇

      gtest项目中包含了两个框架,一个gtest测试框架,一个是gmock框架。gtest类似于java里面的junit,用来做单元测试的;gmock主要是用来mock待测试模块依赖的一些对象,帮助你在测试中去除不必要的依赖,类似与java的jMockEasyMock

    好了,接下来直接上例子吧(注:下面的例子都是在linux下编译运行的,如果要在Windows上,需要看看gtest的文档)。

    gtest demo

      clone下来gtest后,可以在googletest目录中找到make目录:

    ,make目录中的Makefile是gtest帮我们写好的一个使用gtest测试框架来测试模块的例子。我们只需要把这个文件拷贝到写测试模块代码的目录,再改下面几个地方就可以编译运行测试模块。

     1 GTEST_DIR = .. #设置gtest的项目目录
     2 
     3 USER_DIR = ../samples #设置测试代码所在的目录
     4 
     5 CPPFLAGS += -isystem $(GTEST_DIR)/include #设置预处理器参数
     6 
     7 CXXFLAGS += -g -Wall -Wextra -pthread #设置编译器参数
     8 
     9 TESTS = sample1_unittest #设置编译目标
    10 
    11 。。。
    12 
    13 #下面的目标生成规则改成测试模块的
    14 
    15 sample1.o : $(USER_DIR)/sample1.cc $(USER_DIR)/sample1.h $(GTEST_HEADERS)
    16 
    17 $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1.cc
    18 
    19 sample1_unittest.o : $(USER_DIR)/sample1_unittest.cc 
    20 
    21 $(USER_DIR)/sample1.h $(GTEST_HEADERS)
    22 
    23 $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1_unittest.cc
    24 
    25 sample1_unittest : sample1.o sample1_unittest.o gtest_main.a
    26 
    27 $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@

      上面都是make脚本的语法,不清楚的可以先Google下。好了,一起准备就绪后,来看看一个简单的例子。首先,先写个要测试的函数:

    1 bool IsEven(int n) {
    2     return (n % 2) == 0;
    3 }

      这是一个判断一个数是否为偶数的函数,是不是非常的简单~~下面我们就来编写一个简单的测试案例:

    1 TEST(IsEvenTest, EqTest)
    2 {
    3     EXPECT_FALSE(IsEven(1));
    4     EXPECT_TRUE(IsEven(2));
    5 }

      上面可以看到,编写一个测试案例是多么的简单。我们使用了TEST这个宏,它有两个参数,这两个参数的定义是:[TestSuiteName,TestCaseName],我的理解是TestSuiteName是对某个模块总案例名,TestCaseName是这个案例中某个case的名字。

      对检查点的检查,我们上面使用到了EXPECT_FLASE和EXPECT_TRUE这两个宏,这两个宏主要分别用来判断函数返回值是否为false和true。Google还包装了一系列EXPECT_* 和ASSERT_*的宏,而EXPECT系列和ASSERT系列的区别是:

    1. EXPECT_* 失败时,案例继续往下执行。

    2. ASSERT_* 失败时,直接在当前函数中返回,当前函数中ASSERT_*后面的语句将不会执行。

      至于其它具体宏的介绍,可以通过上面给出的链接来查看。

      好了,一起都准备好了,运行的结果是所有的测试都通过。

      如果我们把第一个EXPECT_FALSE改为EXPECT_TRUE的结果呢?答案是测试是失败的,而且会给出具体出错在文件中的哪一行,以及出错的原因。

      这是个很简单的使用gtest的例子,虽然简单,但基本涵盖了使用gtest的流程,而且用这些基本的功能就能解决大部分问题了。至于gtes的一些高级功能,需要的时候可以查上面链接中的文档。

    gmock demo

      编译运行的方式和gtest类似,Makefile文件在googlemock目录中的make目录中,按前面类似的修改这个Makefile文件就行。现在要测试的模块如下:

    1 void func(FooInterface *p)
    2 {
    3     p->DoThis();
    4 }

      这个模块依赖于实现了抽象类FooInterface的对象,FooInterface类定义如下:

    1 class FooInterface {
    2 public:
    3     virtual ~FooInterface() {}
    4     virtual void DoThis() = 0;
    5 };

      现在我们需要mock这个抽象类,gmock通过下面的宏来实现:

    1 class MockFoo : public FooInterface {
    2 public:
    3     MockFoo() {}
    4     MOCK_METHOD0(DoThis, void());
    5 private:
    6     GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
    7 };
     

      MOCK_METHOD*是一个宏,用来mock父类中的虚函数,*表示函数需要接收*个参数。好了,现在有了Mock类,接下来我们开始写测试用例:

    1 class MockFoo : public FooInterface {
    2 public:
    3     MockFoo() {}
    4     MOCK_METHOD0(DoThis, void());
    5 private:
    6     GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
    7 };

      EXPECT_CALL宏表示将会在后面调用foo对象中的DoThis方法,并且调用次数为1。

      一切都准备好了,现在直接make编译运行就可以了,运行结果为:

      如果我们把最后的delete foo去掉会怎么样?

      结果就是gmock会报错提示内存泄露了,但需要注意的是如果在函数func里面里面发生了内存泄露,gmock是检查不出来的。

      最后如果我们把Times中预计的DoThis方法运行次数改为2,结果会怎样?

      结果这个case运行会失败,预计的次数和实际调用次数不符合。

    总结

      上面两个demo也只是个简单的示例,它们仅仅展示了gtest和gmock的基本用法,这也是我们在实际测试时经常需要用到的东西,至于一些高级的功能,需要时可以参考官网文档。

  • 相关阅读:
    hdu 4027 Can you answer these queries? 线段树
    ZOJ1610 Count the Colors 线段树
    poj 2528 Mayor's posters 离散化 线段树
    hdu 1599 find the mincost route floyd求最小环
    POJ 2686 Traveling by Stagecoach 状压DP
    POJ 1990 MooFest 树状数组
    POJ 2955 Brackets 区间DP
    lightoj 1422 Halloween Costumes 区间DP
    模板 有源汇上下界最小流 loj117
    模板 有源汇上下界最大流 loj116
  • 原文地址:https://www.cnblogs.com/chengxuyuancc/p/6434660.html
Copyright © 2011-2022 走看看