Gtest源码剖析:1.实现一个超级简单的测试框架xtest
下面的代码模仿gtest实现,主要说明了以下两点:
ASSERT_*
和EXPECT_*
系列断言的原理和作用.- gtest是怎样通过宏自动注册测试代码让其自动运行的.
#include <iostream>
#include <string>
#include <memory>
#include <vector> #define ASSERT_EQ(a,b) if((a) != (b)) \
{ \
std::cout<<"[ FAIL ] "<<#a<<" not equal "<<#b<<std::endl; \
return; \
} else { \
std::cout<<"[ OK ] "<<std::endl; \
} #define ASSERT_NE(a,b) if((a) == (b)) \
{ \
std::cout<<"[ FAIL ] "<<#a<<" not equal "<<#b<<std::endl; \
return; \
} else { \
std::cout<<"[ OK ] "<<std::endl; \
} #define EXPECT_EQ(a,b) if((a) != (b)) \
{ \
std::cout<<"[ FAIL ] "<<#a<<" not equal "<<#b<<std::endl; \
} else { \
std::cout<<"[ OK ] "<<std::endl; \
} #define EXPECT_NE(a,b) if((a) == (b)) \
{ \
std::cout<<"[ FAIL ] "<<#a<<" not equal "<<#b<<std::endl; \
} else { \
std::cout<<"[ OK ] "<<std::endl; \
} #define MAKE_CLASS_NAME(test_case_name, test_name) MAKI_CLASS_NAME_I(test_case_name, test_name)
#define MAKI_CLASS_NAME_I(test_case_name, test_name) XTest_##test_case_name##_##test_name##_Test
#define XTEST_TEST(test_case_name,test_name) class MAKE_CLASS_NAME(test_case_name, test_name): \
public ::xtest::Test { \
public: \
MAKE_CLASS_NAME(test_case_name, test_name)(): ::xtest::Test(#test_case_name, #test_name) \
{ \
::xtest::UnitTest::regist(std::shared_ptr<::xtest::Test>(this)); \
} \
virtual void testBody(); \
static MAKE_CLASS_NAME(test_case_name, test_name) * instance; \
}; \
MAKE_CLASS_NAME(test_case_name, test_name) * MAKE_CLASS_NAME(test_case_name, test_name) ::instance \
= new MAKE_CLASS_NAME(test_case_name, test_name) ();\
void MAKE_CLASS_NAME(test_case_name, test_name)::testBody() #define TEST(test_case_name, test_name) XTEST_TEST(test_case_name, test_name) namespace xtest { class Test{
friend class UnitTest;
public:
Test(const std::string &n1, const std::string& n2):test_case_name(n1), test_name(n2){
}
virtual void testBody() = ;
std::string test_case_name;
std::string test_name;
private:
Test(const Test&) = delete;
Test& operator=(const Test&) = delete;
}; class UnitTest {
public:
static UnitTest* getInstance();
void Run();
static void regist(std::shared_ptr<Test> const& a);
private:
static UnitTest* instance;
std::vector<std::shared_ptr<Test>> all_tests12;
};
} inline void RUN_ALL_TESTS(){
xtest::UnitTest::getInstance()->Run();
}
#include "xtest.h"
namespace xtest{ UnitTest* UnitTest::instance = NULL;
UnitTest* UnitTest::getInstance(){
if(instance == NULL){
instance = new UnitTest();
}
return instance;
}
void UnitTest::Run(){
std::cout<<"[==========] Start XTest..."<<std::endl;
for(auto i = begin(all_tests12); i!= end(all_tests12); ++i){
std::cout<<"[ RUN ] "<<(*i)->test_case_name<<"."<<(*i)->test_name<<std::endl;
(*i)->testBody();
std::cout<<std::endl;
}
}
void UnitTest::regist(std::shared_ptr<Test>const& a){
getInstance()->all_tests12.push_back(a);
}
}
现在看看怎么用吧
#include "xtest.h" TEST(t1,t2){
ASSERT_EQ(,);
ASSERT_EQ(,);
ASSERT_EQ(,);
}
TEST(t3,t4){
EXPECT_EQ(,);
EXPECT_EQ(,);
EXPECT_EQ(,);
}
int main(int argc, char* argv[]) { RUN_ALL_TESTS();
return ;
}
输出结果:
[==========] Start XTest...
[ RUN ] t1.t2
[ OK ]
[ FAIL ] not equal [ RUN ] t3.t4
[ OK ]
[ FAIL ] not equal
[ FAIL ] not equal
Gtest源码剖析:1.实现一个超级简单的测试框架xtest的更多相关文章
- TreeMap就这么简单【源码剖析】
前言 声明,本文用得是jdk1.8 前面章节回顾: Collection总览 List集合就这么简单[源码剖析] Map集合.散列表.红黑树介绍 HashMap就是这么简单[源码剖析] LinkedH ...
- ConcurrentHashMap基于JDK1.8源码剖析
前言 声明,本文用的是jdk1.8 前面章节回顾: Collection总览 List集合就这么简单[源码剖析] Map集合.散列表.红黑树介绍 HashMap就是这么简单[源码剖析] LinkedH ...
- 【java集合框架源码剖析系列】java源码剖析之TreeSet
本博客将从源码的角度带领大家学习TreeSet相关的知识. 一TreeSet类的定义: public class TreeSet<E> extends AbstractSet<E&g ...
- 【java集合框架源码剖析系列】java源码剖析之HashSet
注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本.本博客将从源码角度带领大家学习关于HashSet的知识. 一HashSet的定义: public class HashSet&l ...
- Netty学习笔记(三)——netty源码剖析
1.Netty启动源码剖析 启动类: public class NettyNioServer { public static void main(String[] args) throws Excep ...
- Ethtool工具源码剖析
Ethtool工具源码剖析 ethool是一个实用的工具,用来给系统管理员以大量的控制网络接口的操作.可以用来控制接口参数,速度,介质类型,双工模式,DMA环设置,硬件校验和,LAN唤醒操作等.本人经 ...
- C# Dictionary源码剖析---哈希处理冲突的方法有:开放定址法、再哈希法、链地址法、建立一个公共溢出区等
C# Dictionary源码剖析 参考:https://blog.csdn.net/exiaojiu/article/details/51252515 http://www.cnblogs.com/ ...
- 一个Python开源项目-腾讯哈勃沙箱源码剖析(上)
前言 2019年来了,2020年还会远吗? 请把下一年的年终奖发一下,谢谢... 回顾逝去的2018年,最大的改变是从一名学生变成了一位工作者,不敢说自己多么的职业化,但是正在努力往那个方向走. 以前 ...
- 跨站请求伪造(csrf),django的settings源码剖析,django的auth模块
目录 一.跨站请求伪造(csrf) 1. 什么是csrf 2. 钓鱼网站原理 3. 如何解决csrf (1)思路: (2)实现方法 (3)实现的具体代码 3. csrf相关的装饰器 (1)csrf_p ...
随机推荐
- DOM笔记(十):JavaScript正则表达式
一.RegExp ECMAScript通过RegExp类型类支持正则表达式,语法和Perl类似: var exp = /pattern/flags; patternb部分是任何简单的或复杂的正则表达式 ...
- 数往知来 ADO.NET <八>
ADO.NET基础 学习目的:通过程序访问数据库 ,ADO.NET就是一组类库, -->connection 用来连接数据库的类 语法:首先需要一个连接字符串 -->以SQL serv ...
- ubuntu ip
一.使用命令设置Ubuntu IP地址 1.修改配置文件blacklist.conf禁用IPV6 sudo vi /etc/modprobe.d/blacklist.conf 在文档最后添加 blac ...
- 30个有关Python的小技巧
从我开始学习python的时候,我就开始自己总结一个python小技巧的集合.后来当我什么时候在Stack Overflow或者在某个开源软件里看到一段很酷代码的时候,我就很惊讶:原来还能这么做!,当 ...
- pku3277 City Horizon
http://poj.org/problem?id=3277 线段树,离散化,成段更新 #include <stdio.h> #include <stdlib.h> #defi ...
- Axis2在Web项目中整合Spring
一.说明: 上一篇说了Axis2与Web项目的整合(详情 :Axis2与Web项目整合)过程,如果说在Web项目中使用了Spring框架,那么又改如何进行Axis2相关的配置操作呢? 二.Axis2 ...
- js实现异步循环
@(编程) 问题 实现异步循环时,你可能会遇到问题. 让我们试着写一个异步方法,每秒打印一次循环的索引值. for(var i = 0; i < 5; i++) { setTimeout(fun ...
- Java中的BASE64
located in rt.jar... public class sun.misc.BASE64Encoder extends sun.misc.CharacterEncoder{ //.. } p ...
- HDU 3696 Farm Game(dp+拓扑排序)
Farm Game Problem Description “Farm Game” is one of the most popular games in online community. In t ...
- [转]ViewPager onPageChangeListener总结
android ViewPager滑动事件讲解 首先ViewPager在处理滑动事件的时候要用到OnPageChangeListener OnPageChangeListener这个接口需要实现三个方 ...