gTest详解
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对象主要用于包含如下信息:
测试案例名称(testcase name)
测试名称(test name)
该案例是否需要执行
执行案例时,用于创建Test对象的函数指针
测试结果
我们还看到,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对象就出来了
TEST宏中的两个参数,第一个参数testcase_name,就是TestCase对象的名称,第二个参数test_name就是Test对象的名称。而TestInfo包含了一个测试案例的一系列信息。
一个TestCase对象对应一个或多个TestInfo对象。
总结一下gtest里的几个关键的对象:
- UnitTest 单例,总管整个测试,包括测试环境信息,当前执行状态等等
- Test 我们自己编写的,或通过TEST,TEST_F等宏展开后的Test对象,管理着测试案例的前后事件,具体的执行代码TestBody。
- TestCase 测试案例对象,管理着基于TestCase的前后事件,管理内部多个TestInfo。
- TestInfo 管理着测试案例的基本信息,包括Test对象的创建方法。
一个简单的UML图如下

4. 撸一个山寨的
撸了一个山寨的,https://github.com/sld666666/TestUnit
gTest详解的更多相关文章
- 【转】gitlab CI流水线配置文件.gitlab-ci.yml详解
目录 GitLab CI流水线配置文件.gitlab-ci.yml详解 实验环境 GitLab CI介绍 .gitlab-ci.yml 配置参数 参数详解 script image services ...
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
- Android Notification 详解——基本操作
Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...
- Git初探--笔记整理和Git命令详解
几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
随机推荐
- Mysql 5.7 使用SSL安全连接
MySQL默认的数据通道是不加密的,在一些安全性要求特别高的场景下,我们需要配置MySQL端口为SSL,使得数据通道加密处理,避免敏感信息泄漏和被篡改.当然,启用MySQL SSL之后,由于每个数据包 ...
- Ubuntu install Docker
首先需要说明的是,根据Docker的官方文档,Docker的安装必须在64位的机子上.这里只说明Ubuntu 14.04与16.04,我成功安装成功过Ubuntu 14.04,16.04还没有测试过, ...
- pythonchallenge 解谜 Level 0
解谜地址: http://www.pythonchallenge.com/pc/def/0.html 这题没什么难度,意思就是得到2的38次方的值,然后,替换 http://www.pythoncha ...
- Jvascript简介
一.Javascript就是我们所说的脚本语言.它不同于C++/java等语言,它更加灵活! 正因为其灵活性,没有那么多的规章制度,也是我们容易学的地方,但很多时候也是 令人无奈的地方! 二.我们要知 ...
- 常用Jquery插件整理
虽然自己也写过插件,但JQuery插件种类的繁多,大多时候,我还是使用别人写好的插件,这些都是我用了同类插件里较为不错的一些,今天就整理一下公开放出来. UI: jquery.HooRay(哈哈,自己 ...
- mock the facade
mock the facade: Auth::shouldReceive('user')->andReturn($user = m::mock('StdClass')); $user->s ...
- struts2所有组件
struts2所有组件(动作,结果,拦截器) 动作在框架中可作为MVC模式的模型.这个角色的主要职责是控制业务逻辑,动作使用execute()方法来实现这个功能. 这个方法中的代码应该只关注与请求相关 ...
- MongoDB的安装和配置成服务的三种方法和一些难点
1. Hotfix KB2731284 or later update is not installed的问题: If you are running any edition of Windows S ...
- Python模拟删除字符串两边的空白
目标: 1.使用string模块的whitespace 2.删除左边.右边以及两边的空白 代码如下: [root@localhost python]# cat rmspace.py #!/usr/bi ...
- Windows RabbitMQ 命令
启动: 后台运行:rabbitmq-server -detached D:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.6\sbin>ra ...