Gtest源码剖析:1.实现一个超级简单的测试框架xtest
2014-06-05 15:32
423 查看
下面的代码模仿gtest实现,主要说明了以下两点:
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() = 0; 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(1,1); ASSERT_EQ(1,2); ASSERT_EQ(2,3); } TEST(t3,t4){ EXPECT_EQ(1,1); EXPECT_EQ(1,2); EXPECT_EQ(2,3); } int main(int argc, char* argv[]) { RUN_ALL_TESTS(); return 0; }
输出结果:
[==========] Start XTest... [ RUN ] t1.t2 [ OK ] [ FAIL ] 1 not equal 2 [ RUN ] t3.t4 [ OK ] [ FAIL ] 1 not equal 2 [ FAIL ] 2 not equal 3
相关文章推荐
- 用Reactor框架实现一个简单的tcp服务器
- 用完成端口(IOCP)实现一个简单的服务器框架
- 介绍一个超级简单的jqurey实现ajax
- 使用Enumerable模块实现简单的测试框架并进行数据统计
- 一个通用的单元测试框架的思考和设计06-实现篇-自动管理测试数据-如何临时关闭数据外键约束
- 用TestComplete实现一个关键字驱动测试框架
- Pexpect简单的测试——一个 expect的python实现
- 一个通用的单元测试框架的思考和设计07-实现篇-自动管理测试数据-如何为自增长主键id赋值
- 我写的一个简单自动化测试框架
- 一个通用的单元测试框架的思考和设计07-实现篇-自动管理测试数据-如何为自增长主键id赋值
- 发布一个超级mini的ajax源代码(含简单框架)
- Emit学习-实战篇-实现一个简单的AOP框架(三)
- WF4.0实战(五):实现一个直观易扩展的自动测试框架
- 利用boost::asio实现一个简单的服务器框架
- 用Visual studio2005的单元测试框架实现一个简单的计算器
- 如何用phototype框架实现一个简单的ajax验证
- Emit学习-实战篇-实现一个简单的AOP框架(二)
- 超级简单:一个超轻量级的测试平台
- 一个通用的单元测试框架的思考和设计06-实现篇-自动管理测试数据-如何临时关闭数据外键约束
- 一个通用的单元测试框架的思考和设计04-实现篇-自动管理测试数据