1. 安装使用

1.1 安装

在https://code.google.com/p/googletest/ 下载源码

进入msvc, 注意编译方式, 如果是dll, 选择 gtest-md

编译生成lib文件, 然后引入.文件即可使用

1.2 使用

#include "gtest/gtest.h"
int _tmain(int argc, _TCHAR* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

当然我们也可以输出到xml

int _tmain(int argc, _TCHAR* argv[])
{
testing::GTEST_FLAG(output) = "xml:";
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

2. 断言

断言的宏可以分为两类ASSERT系列和EXPECT系列。

TEST(StringCmpTest, Demo)
{
EXPECT_EQ(3, add(1, 2));
ASSERT_EQ(3, add(1, 2));
}

我们再来看下所支持的宏

  • ASSERT_EQ
  • ASSERT_NE
  • ASSERT_LE
  • ASSERT_LT
  • ASSERT_GE
  • ASSERT_GT

  • EXPECT_EQ
  • EXPECT_NE
  • EXPECT_LE
  • EXPECT_LT
  • EXPECT_GE
  • EXPECT_GT

  • ASSERT_TRUE
  • ASSERT_FALSE

  • ASSERT_STREQ
  • ASSERT_STRNE
  • ASSERT_STRCASEEQ
  • ASSERT_STRCASENE

  • ASSERT_FLOAT_EQ
  • ASSERT_DOUBLE_EQ

直接返回成功还是失败

  • FAIL();
  • ADD_FAILURE();

Predicate Assertions

在使用EXPECT_TRUE或ASSERT_TRUE时,有时希望能够输出更加详细的信息,比如检查一个函数的返回值TRUE还是FALSE时,希望能够输出传入的参数是什么,以便失败后好跟踪。因此提供了如下的断言:

  • ASSERT_PRED1(pred1, val1);
  • ASSERT_PRED2(pred2, val1, val2);

如果对这样的输出不满意的话,还可以自定义输出格式化

  • ASSERT_PRED_FORMAT1(pred_format1, val1);`
  • ASSERT_PRED_FORMAT2(pred_format2, val1, val2);

例子

如果我们有这样一个类Arithmetic

我们只需要新建一个ArithmeticUnit.cpp文件,然后写下如下代码:

#include "stdafx.h"
#include "Arithmetic.h"
#include "gtest/gtest.h" TEST(Arithmetic, add){
Arithmetic arith;
int a(1), b(2);
EXPECT_EQ(3, arith.add(1, 2));
}

3. 深入解析gTest

首先从TEST宏入手, 我们看下宏的定义

//1
define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name) //2
#define GTEST_TEST(test_case_name, test_name)\
GTEST_TEST_(test_case_name, test_name, \
::testing::Test, ::testing::internal::GetTestTypeId()) //3
#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
public:\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
private:\
virtual void TestBody();\
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
.... 所以
1. 最终展开的宏是继承自testing::Test类
2. 我们最终写的代码是放在TestBody()中的
3. 通过静态变量test_info_,调用MakeAndRegisterTestInfo对测试案例进行注册。

看下MakeAndRegisterTestInfo 是如何实现的

TestInfo* MakeAndRegisterTestInfo(
const char* test_case_name,
const char* name,
const char* type_param,
const char* value_param,
TypeId fixture_class_id,
SetUpTestCaseFunc set_up_tc,
TearDownTestCaseFunc tear_down_tc,
TestFactoryBase* factory) {
TestInfo* const test_info =
new TestInfo(test_case_name, name, type_param, value_param,
fixture_class_id, factory);
GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
return test_info;
}

TestInfo对象主要用于包含如下信息:

  1. 测试案例名称(testcase name)

  2. 测试名称(test name)

  3. 该案例是否需要执行

  4. 执行案例时,用于创建Test对象的函数指针

  5. 测试结果

我们还看到,TestInfo的构造函数中,非常重要的一个参数就是工厂对象

internal::TestFactoryBase* factory

它主要负责在运行测试案例时创建出Test对象

new ::testing::internal::TestFactoryImpl<\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>)

我们再来看下 TestFactoryImpl 是如何实现的

template <class TestClass>
class TestFactoryImpl : public TestFactoryBase {
public:
virtual Test* CreateTest() { return new TestClass; }
};

我靠, 这也能算是工厂吗~

不过总之流程是, 我们要创建一个测试对象的时候,先调用factory的CreateTest()方法 创建TestInfo对象, 再通过 GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);对TestInfo对象进行注册

UnitTest 是单例

UnitTestImpl 是实现

void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc,
TestInfo * test_info) {
// 获取或创建了一个TestCase对象,并将testinfo添加到TestCase对象中。
GetTestCase(test_info->test_case_name(),
test_info->test_case_comment(),
set_up_tc,
tear_down_tc)->AddTestInfo(test_info);
}

这里TestCase对象就出来了

  1. TEST宏中的两个参数,第一个参数testcase_name,就是TestCase对象的名称,第二个参数test_name就是Test对象的名称。而TestInfo包含了一个测试案例的一系列信息。

  2. 一个TestCase对象对应一个或多个TestInfo对象。

总结一下gtest里的几个关键的对象:

  1. UnitTest 单例,总管整个测试,包括测试环境信息,当前执行状态等等
  2. Test 我们自己编写的,或通过TEST,TEST_F等宏展开后的Test对象,管理着测试案例的前后事件,具体的执行代码TestBody。
  3. TestCase 测试案例对象,管理着基于TestCase的前后事件,管理内部多个TestInfo。
  4. TestInfo 管理着测试案例的基本信息,包括Test对象的创建方法。

一个简单的UML图如下

4. 撸一个山寨的

撸了一个山寨的,https://github.com/sld666666/TestUnit

gTest详解的更多相关文章

  1. 【转】gitlab CI流水线配置文件.gitlab-ci.yml详解

    目录 GitLab CI流水线配置文件.gitlab-ci.yml详解 实验环境 GitLab CI介绍 .gitlab-ci.yml 配置参数 参数详解 script image services ...

  2. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  3. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  4. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  5. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  6. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  7. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  8. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  9. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

随机推荐

  1. ZeroMQ接口函数之 :zmq_msg_more - 指出是不是还有更多的消息部分可以接收

    ZeroMQ 官方地址 :http://api.zeromq.org/4-2:zmq_msg_more zmq_msg_more(3) ØMQ Manual - ØMQ/3.2.5 Name zmq_ ...

  2. easy ui插件

    简介: easy UI是类似于jQuery UI的插件库 注意:多脚本同时使用时,注意脚本冲突问题. 常用插件: 1.tree插件(tree插件实现动态树形菜单) 2.datagrid插件(datag ...

  3. 安装phonegap3.2

    安装phonegap3.2,要用node.js,还要安装git  

  4. 用PS去除图片中文字的6个方法

    转自:http://www.u148.net/article/486.html 1.使用仿制图章工具去除文字. 这是比较常用的方法.具体的操作是,选取仿制图章工具,按住Alt键,在无文字区域点击相似的 ...

  5. centos建立回收站

    linux下的回收站在每一个当前用户目录./local/share/Trash中. 也可以给linux添加一个回收站. mkdir /tmp/trash_tmp 建立一个回收站目录 vi /bin/t ...

  6. 如何给你的LinuxVPS装个远程桌面

    有些人抱怨Linux的系统没有桌面,用着实在是不方便.今天整理一下网上的教程,给VPS装个桌面环境.Centos系统+X Window+GNOME Desktop. 此程序会安装无数乱七八糟的东西到你 ...

  7. WebApi接口传参不再困惑(4):传参详解(转载)

    WebApi接口传参不再困惑(4):传参详解   前言:还记得刚使用WebApi那会儿,被它的传参机制折腾了好久,查阅了半天资料.如今,使用WebApi也有段时间了,今天就记录下API接口传参的一些方 ...

  8. HTTPS 协议和原理

    1 HTTPS 协议概述 HTTPS 可以认为是 HTTP + TLS.HTTP 协议大家耳熟能详了,目前大部分 WEB 应用和网站都是使用 HTTP 协议传输的. TLS 是传输层加密协议,它的前身 ...

  9. sed 引入shell变量

    双单引号即可 1.eval sed ’s/$a/$b/’ filename2.sed "s/$a/$b/" filename3.sed ’s/’$a’/’$b’/’ filenam ...

  10. win10没有新建文件夹

    win10没有新建文件夹 win10系统,电脑点击右键没有新建文件夹选项. 工具/原料   win10 系统台式机 方法/步骤     电脑左下角搜素出输入:cmd   出现以下画面   在命令指示符 ...