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. CentOS7和win7双系统启动项

    1.添加win7启动项编辑文件 /boot/grub2/grub2.conf menuentry 'Windows 7' { insmod ntfs set root='hd0,1' chainloa ...

  2. EF 5 最佳实践白皮书

    Performance Considerations for Entity Framework 5 By David Obando, Eric Dettinger and others Publish ...

  3. JavaBean对象与Map对象互相转化

    /** * 使用org.apache.commons.beanutils进行转换 */ class A { public static Object mapToObject(Map<String ...

  4. arcmap配置的mxd慢的问题

    http://www.360doc.com/content/13/0220/09/3046928_266688511.shtml

  5. Flume_使用

    案例一: source:hive.log channel: memory  sink: logger输出 拷贝一份flume-conf.properties.template改名为hive-mem-l ...

  6. mysql cpu和内存监控

    mysqlMem 监控:#!/bin/bashPid=`/bin/ps -ef|grep mysqld|grep -Ev "grep|safe"|awk '{print $2}'` ...

  7. NeoKylin5.6下安装部署达梦(DM7)数据库

    1.准备操作系统 1.1 系统登录界面 1.2 操作系统版本信息 [root@jdbh ~]# uname -ra Linux jdbh -.el5xen # SMP Fri Jul :: EDT x ...

  8. JavaScript模拟鼠标右键菜单

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. 多边形碰撞 -- SAT方法

    检测凸多边形碰撞的一种简单的方法是SAT(Separating Axis Theorem),即分离轴定理. 原理:将多边形投影到一条向量上,看这两个多边形的投影是否重叠.如果不重叠,则认为这两个多边形 ...

  10. jquery数组(排序)

    sort(); html: <h3>字符串数组排序前</h3> <div id="show1"></div> <h3>排 ...