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 ...
随机推荐
- 第一个自定义HTML网页
前言 已经好几天没玩LOL了,实在手痒,下载了游戏,又卸载了,坦言:毛爷爷说的”好好天天向上“,真不容易.但还是回到学习个状态了,开始写,就“根本停不下来”,我也慢慢感受到代码的快乐了,并且想总结出一 ...
- Hibernate中openSession() 与 getCurrentSession()的区别
1 getCurrentSession创建的session会和绑定到当前线程,而openSession每次创建新的session. 2 getCurrentSession创建的线程会在事务回滚或事物提 ...
- home-brew 安装&下载
安装: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)&qu ...
- Linux入门视频
为了方便新手学习Linux,本人专门录制了以下Linux初级视频方便学习,本系列多媒体教程已完成的博文: 轻松学习Linux之入门篇 http://chenguang.blog.51cto.com/3 ...
- 第三百五十五天 how can I 坚持
快一年了,三百五十五天了,等写个程序算算时间,看看日期和天数能不能对的上,哈哈. 计划还是未制定,天气预报还是没有写完,立马行动,发完这个博客,立马行动. 计划:设计模式1个月,三大框架3个月,计算机 ...
- 转】mysql数据库delete数据时不支持表别名
原博文出自于: http://www.cnblogs.com/xdp-gacl/p/4012853.html 感谢! 今天在帮同事查看一条删除的SQL语句执行出错的问题 SQL语句如下: 1 DELE ...
- S3
S3是Amazon EMR的一部分,它提供了一些Wikipedia的浏览统计数据,这些浏览数据的格式便于Spark测试.
- Javascript事件处理进阶
这篇文章是我在看乌龟书<编写可维护的Javascript>发现的一篇写的非常好的章节,在这里我并不会教大家什么是绑定事件等比较基础的事.有兴趣了解DOM事件的同学们,可以去w3cschoo ...
- NLP初步
[NLP初步] NLP是Natural Lanuage Process的缩写.搜索引擎可以通过关词匹配和完成很多的任务, 比如话题搜索(搜索包含律师, 法院, 控告等词的文档), 但是搜索引擎无法理解 ...
- gcc -D
[gcc -D] -D name Predefine name as a macro, with definition 1. 通常debug和release版的区别就在于是否有DEBUG宏,DEBUG ...