Google 测试框架 g-Test 使用教程

Description: 这篇文章简明介绍了 google 开源的一款 C++ 方向的测试框架 Gtest 的使用方法做简单介绍,为后续整理发布的数据库引擎开发项目(目前还没发布到博客中)做单元,模块测试方面的技术支撑。


G-Test 的安装

  • 通过 github 页面下载 gtest 的源码压缩包,命令如下

   $wget https://github.com/google/googletest/archive/master.zip 
  • 解压之后,在目录下面看到 CMakeList.txt 文件,可知使用的是 cmake 编译工具,保证虚拟机处于联网(NAT模式),输入命令下载 cmake 编译工具

  $apt-get install cmake 
  • 下载 cmake 结束之后,测试其是否能够正常工作

$cmake
如果正常工作会显示如下内容
Usage
  cmake [options] 
  cmake [options] 
  Options -C  = Pre-load a script to populate the cache. 

编译安装 gTest


    $ mkdir cmake_dir
    $ cd cmake_dir
    $ cmake ../
    正确编译,显示信息如下
-- The C compiler identification is GNU 4.9.2
-- The CXX compiler identification is GNU 4.9.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
...
-- Found Threads: TRUE  
-- Configuring done
-- Generating done
-- Build files have been written to: /gTester/googletest-master/cmake_dir
 
在这里我们创建 cmake_dir 文件夹,并在该文件夹的下面执行 cmake 操作的目的是为了让 cmake 编译生成的中间文件与下载的 gTest 的项目文件二者之间分离开,不然会混淆. 在 cmake_dir 文件夹中生成的中间文件如下:

 CMakeCache.txt  CMakeFiles  cmake_install.cmake  CTestTestfile.cmake  googlemock  Makefile

继续输入 make && make install 来安装 gTest,如正确编译安装显示信息如下:


 Scanning dependencies of target gmock
[ 14%] Building CXX object googlemock/CMakeFiles/gmock.dir/__/googletest/src/gtest-all.cc.o
[ 28%] Building CXX object googlemock/CMakeFiles/gmock.dir/src/gmock-all.cc.o
Linking CXX static library libgmock.a
...
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/lib/libgmock.a
-- Installing: /usr/local/lib/libgmock_main.a
-- Installing: /usr/local/include/gmock
-- Installing: /usr/local/include/gmock/gmock-generated-actions.h
-- Installing: /usr/local/include/gmock/gmock-cardinalities.h
-- Installing: /usr/local/include/gmock/gmock-actions.h
... 

gTest 的入门级使用例子

  • 使用 gTest 来编写最简单的测试用例
    • 首先编写 C++ 文件

  // test.hpp
#ifndef TEST_HPP__
#define TEST_HPP__

int getValue(int _value);

#endif

 // test.cpp
#include "test.hpp"
#include 

int getValue( int _value ){
    return _value ;
}
 
  • 编写包含 gTest库函数的 C++ 测试文件

#include "test.hpp"
#include "gtest/gtest.h"

// first we test ASSERT_TRUE

void test_ASSERT_TRUE(){
  ASSERT_TRUE(false) ;
}

void test_EXPECT_TRUE(){
   EXPECT_TRUE(false) ;
}

int main( void ){
  test_EXPECT_TRUE();

  return 0;
}

  • 编写 Makefile 文件

GTEST_DIR=/gTester/googletest-master/googletest

USER_DIR= ./

CPPFLAGS += -I$(GTEST_DIR)/include

CXXFLAGS += -g -Wall -Wextra

TESTS = test_tester

GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
                $(GTEST_DIR)/include/gtest/internal/*.h

all : $(TESTS)

clean :
        rm -f $(TESTS) *.a *.o

GTEST_SRCS_= $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)

gtest-all.o : $(GTEST_SRCS_)
        $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
                $(GTEST_DIR)/src/gtest-all.cc


gtest_main.o : $(GTEST_SRCS_)
        $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c $(GTEST_DIR)/src/gtest_main.cc  

gtest.a : gtest-all.o
        $(AR) $(ARFLAGS) $@ $^  

gtest_main.a : gtest-all.o gtest_main.o
        $(AR) $(ARFLAGS) $@ $^  


test.o : $(USER_DIR)/test.cpp $(USER_DIR)/test.hpp $(GTEST_HEADERS)
        $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/test.cpp

test_tester.o : $(USER_DIR)/test_tester.cpp $(USER_DIR)/test.hpp $(GTEST_HEADERS)
        $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/test_tester.cpp

test_tester : test.o test_tester.o gtest_main.a
        $(CXX) $(CPPFLAGS) $(CXXFLAG) -pthread  $^ -o $@
  • 输入 make 命令生成可执行文件 test_tester
  • 运行 gTest 的测试文件,查看输出结果

 .//test_tester.cpp:12: Failure
  Value of: false
  Actual: false
  Expected: true 
 

gTest 中断言介绍

  • ASSERT_* 的断言函数如果判定最终结果不满足判定输出值,将会发出 断言失败 + 终止程序的结果

  • EXPECT_* 的断言函数如果判断最终结果不满足判定输出值,将仅会发出 断言失败 的提示信息

基本断言说明


ASSERT_TRUE (condition); 
ASSERT_FALSE (condition) ;
上述断言函数是这样的: 括号中的 condition 可以是一个返回结果为布尔值的函数,也可以是一个不二变量,同样也可以是一个逻辑表达式,只要最终返回的结果是布尔值就可以。而两个函数 ASSERT_TRUE 要求这个布尔值必须是 TRUE/真值,如果不是真便会输出'致命错误'并退出当前正在执行的函数。 ASSERT_FALSE 方法刚好相反,它期待的是一个 FALSE/假值,如果不满足同样输出'致命错误'信息,并退出当前正在执行的方法(程序)。

   EXPECT_TRUE(condition) ;
   EXPECT_FALSE(condition) ;
上述函数的断言是这样的: 如果括号中的 condition 变量返回的布尔值与断言期待的布尔值不同的话,不会退出当前正在执行的方法/程序。 它会继续允许程序的继续运行,但是会输出执行错误的提示信息(如果错误信息流定向是控制台显示器的话) ### 基于两值比较的断言函数说明 + 在基于而知比较的断言函数中,传入的参数必须要满足下面两种条件中的一种 + 是基本类型,可以直接进行逻辑比较 + 如果是符合类似(class ,struct)是需要重载比较运算符的 + 需要注意的是,如果传入的是指针类型的话,判定的并不是指针指向的数值内容是否相同,而是会判定指针是否指向同一块内存空间 + 如果需要判定指针指向字符串的逻辑关系,不要使用这一系列的断言函数

    ASSERT_EQ(expected, actual) ;  expected==actual
    ASSERT_NE(expected, actual) ;  expected!=actual
    ASSERT_LT(expected, actual) ;  expected 小于 actual, LT(less than)
    ASSERT_LE(expected, actual) ;  expected 小于等于 actual, LE(less equal)
    ASSERT_GT(expected, actual) ;  expected 大于 actual, GT(greater than)
    ASSERT_GE(expected, actual) ;  expected 大于等于 actual, GE(greater equal)

  EXPECT_EQ(expected, actual) ;
  EXPECT_NE(expected, actual) ;
  EXPECT_LT(expected, actual) ;
  EXPECT_LE(expected, actual) ;
  EXPECT_GT(expected, actual) ;
  EXPECT_GE(expected, actual) ;

基于字符串的比较断言说明


  ASSERT_STREQ(str1,str2); str1's content = str2's content
  ASSERT_STRNE(str1,str2); str1's content != str2's content
 ASSERT_STRCASEEQ(str1,str2); str1's content = str2's content ,ignoring characters case
 ASSERT_STRCASENE(str1,str2); ignoring string characters' case, str1's content != str2's content