添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

一、安装googletest

单测对程序员而言是提升代码质量最重要、最有效的一个措施,对程序员来说,要想写一个好的程序,那么必定少不了好的单元测试。googletest(gtest)是google开发出来的一个开源的、跨平台的测试框架,是C++中最出名的测试框架。

gtest支持linux、windows以及mac系统,安装它依赖下面几项:

  • gtest源码:gtest属于开源项目,代码仓库 https://github.com/google/googletest
  • cmake:gtest使用cmake构建项目,编译需要cmake环境, cmake下载地址
  • 编译器:linux环境下可使用g++编译,windows环境下使用vs或者clion等工具编译,mac环境使用xcode或clion等工具编译。
  • 这里的测试环境为mac+clion(付费), clion下载地址 ,选择clion是因为clion跨平台。

    windows环境除了配置clion编译环境以外,其他步骤和mac系统一致。

    1.1 环境配置

    第一步,先使用git克隆代码到本地,注意最好不要放到中文路径了。

    第三步,安装clion,linux和mac环境下安装clion和gcc环境就可以使用了,windows配置clion编译环境可参考 Window10上CLion极简配置教程

    1.2 编译gtest库

    配置好环境后,使用clion打开代码目录,然后载入代码目录,选择 gtest 项目编译生成:

    编译成功后生成 libgtestd.a 文件到cmake编译路径的 lib 路径下:

    生成的 libgtestd.a 即为gtest的库文件,项目中引用这个库文件就能使用gtest了。

    二、使用googletest

    2.1 引入库

    将libgtestd.a文件拷贝到代码根路径的lib路径下,在CMakeList.txt中加上以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #include "gtest/gtest.h"
    int add ( int a , int b ) {
    return a + b ;
    }
    TEST ( add , zero ) {
    EXPECT_EQ ( 0 , add ( 0 , 0 ) ) ;
    }
    TEST ( add , positive_number ) {
    EXPECT_EQ ( 3 , add ( 1 , 2 ) ) ;
    }
    TEST ( add , negative_number ) {
    EXPECT_EQ ( - 3 , add ( - 1 , - 2 ) ) ;
    }
    int main ( ) {
    :: testing :: InitGoogleTest ( ) ;
    return RUN_ALL_TESTS ( ) ;
    }

    执行结果:

    ![](/Users/maqian/Library/Application Support/typora-user-images/image-20200208101215701.png)

    三、gtest的使用教程

    参考文档: Googletest Primer ,google官方出品。

    3.1 基本用法

    gtest最基本的用法就是断言,它内部提供了很多种断言方式,例如:

    [ OK ] add.zero (0 ms) [ RUN ] add.positive_number [ OK ] add.positive_number (0 ms) [ RUN ] add.negative_number [ OK ] add.negative_number (0 ms) TEST(add, negative_number) { EXPECT_EQ(-3, add(-1, 2)) << "this is a incorrect test";
  • 开始测试pop。
  • 从直观上来看,所有和pop相关的测试案例都要这么来写,要先推入元素,再弹出。而实际上,步骤1和步骤2是和本轮测试无关,它只起到了初始化数据的作用,它是多余的,但是所有的测试案例又不得不做这一步操作。那么有没有办法解决这个问题呢?有!Test Fixtures的就是解决这种问题的,它可以在测试案例开始前自动生成好需要的数据。

    定义了一个简单的 的类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    TEST_F ( stack_test , push ) {
    EXPECT_EQ ( stack1 .size ( ) , 2 ) ;
    EXPECT_EQ ( stack2 .size ( ) , 0 ) ;
    stack2 .push ( 1 ) ;
    EXPECT_EQ ( stack2 .size ( ) , 1 ) ;
    }
    TEST_F ( stack_test , pop ) {
    EXPECT_EQ ( stack1 .size ( ) , 2 ) ;
    EXPECT_EQ ( stack2 .size ( ) , 0 ) ;
    stack1 .pop ( ) ;
    EXPECT_EQ ( stack1 .size ( ) , 1 ) ;
    }

    在执行TEST_F之前,gtest会自动构建一个stack_test的实例,并执行SetUp函数。也就是说,当真正执行到我们的测试代码的时候,就已经存在一个初始化好的测试环境了。这个时候可以直接访问stack_test的内部成员,通过成员变量来做单元测试。

    原理来看其实很简单,就是把初始化的过程交给了gtest来完成,它来帮我们实例对象,进行初始化,我们直接用就行。

    测试结果:

    5.1 clion环境跨平台使用gtest

    如何在不改变CMakeList.txt的情况下跨平台使用gtest?配置CMakeList,根据不同平台读取不同的库:

    # 根据不同平台设置库的目录 if (UNIX AND NOT APPLE) # unix非苹果系统 set(PROJ_LIBRARY_PATH /home/maqian/code/lib) set(GTEST_LIBRARY_NAME libgtestd.a) elseif (WIN32) # windwos系统 set(PROJ_LIBRARY_PATH d:/mingw64/lib) set(GTEST_LIBRARY_NAME libgtestd.a) elseif (APPLE) # mac系统 set(PROJ_LIBRARY_PATH /Users/maqian/code/lib) set(GTEST_LIBRARY_NAME libgtestd.a) else () # 未知系统 MESSAGE(STATUS "other platform: ${CMAKE_SYSTEM_NAME}") endif () # 引入链接库目录 link_directories(${PROJ_LIBRARY_PATH}) # 链接库到目标 target_link_libraries(xxxx ${GTEST_LIBRARY_NAME})
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 根据不同平台设置库的目录
    if ( UNIX AND NOT APPLE ) # unix非苹果系统
    set ( PROJ_LIBRARY_PATH / home / maqian / code / lib )
    set ( GTEST_LIBRARY_NAME libgtestd .a )
    elseif ( WIN32 ) # windwos系统
    set ( PROJ_LIBRARY _ PATH d : / mingw64 / lib )
    set ( GTEST_LIBRARY_NAME libgtestd .a )
    elseif ( APPLE ) # mac系统
    set ( PROJ_LIBRARY_PATH / Users / maqian / code / lib )
    set ( GTEST_LIBRARY_NAME libgtestd .a )
    else ( ) # 未知系统
    MESSAGE ( STATUS "other platform: ${CMAKE_SYSTEM_NAME}" )
    endif ( )
    # 引入链接库目录
    link_directories ( $ { PROJ_LIBRARY_PATH } )
    # 链接库到目标
    target_link_libraries ( xxxx $ { GTEST_LIBRARY_NAME } )
    默认情况下,goland(jetbrains家的软件:idea、pycharm、phpstorm以及webstorm都是一样)安装protobuf插件后只会在一个特定的库路径下搜索proto文件。如果... 07月25日 2 一、文件流 C++的IO类中定义了三个文件读写流fstream、ifstream以及ofstream,它们都继承于相同的父类istream,通过不同的实现以实现不同的文件流操作。 三者的区别为: if... 12月26日 评论 使用形式: using指令(using directive)的使用形式为using namespace std。 using声明(using declaration)的使用形式为using std::... 11月07日 评论 一、const和成员函数的故事 const的用途有以下几种: 修饰全局、局部、成员变量 修饰成员函数 修饰变量的时候const限制了变量在整个程序运行期间都是不能修改的,而修饰成员函数的时候限制函数内... 10月19日 1