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 的背景. ...
随机推荐
- 用户 'IIS APPPOOL\DefaultAppPool' 登录失败。
今天新建了一个ASP.NET(Language=C#)网站,配置好数据库后编写了几行代码测试数据库的是否能正常使用. 当运行程序时,第一个页面都没有打开就出现了错误(因为我首页就访问数据库,填充一些D ...
- Python之路第一课Day1--随堂笔记
课堂大纲: 一.Python介绍 二.发展史 三.Python 2 or 3? 四.安装 五.Hello World程序 六.变量 七.用户输入 八.模块初识 九..pyc是个什么鬼? 十.数据类型初 ...
- 区间dp
转载:http://www.cnblogs.com/ziyi--caolu/archive/2013/08/04/3236035.html
- dblink嵌套场景下 查询出现:ORACLE ORA-00600错误的解决
前段时间在做oracle查询的时候遇到了一个非常奇怪的现象,现将现象和解决过程记录下来,以备查看: 环境描述:A数据库通过dblink访问B数据库的视图,B数据库的视图的数据是通过B的dblink连接 ...
- IOS ReactiveCocoa
一 前提: 在iOS开发过程中,当某些事件响应时,需处理的某些业务逻辑 Eg. 按钮点击:action ScrollView滚动:delegate 属性值改变:KVO ReactiveCocoa为事件 ...
- mysql 主主互备
双机热备的概念简单说一下,就是要保持两个数据库的状态自动同步.对任何一个数据库的操作都自动应用到另外一个数据库,始终保持两个数据库数据一致. 这样做的好处多. 1. 可以做灾备,其中一个坏了可以切换到 ...
- 分享一个oraclehelper
分享一个拿即用的oraclehelper 首先要引用本机中的oralce access,如果是64位的话,也必须是64位运行,不然会报连接为空connection 等于null. using Orac ...
- javascript中矩形的碰撞检测---- 计算碰撞部分的面积
今天在做一个拖拽改变元素排序的东西的时候,在做被拖动元素同时碰撞到两个元素时,究竟应该与哪个元素交换位置的问题上,纠结到崩溃,实在是想不到别的办法去做了,只能去想办法计算碰撞的面积. 这应该不是最合适 ...
- C#转摘
尽量用Func和lambda解决函数变量问题,用var, dynamic来解决动态变量问题
- vpn
https://itunes.apple.com/us/app/sonicwall-mobile-connect/id822514576?mt=12