zoukankan      html  css  js  c++  java
  • CppUnit使用和源码解析

    前言

      CppUnit是一个开源的单元测试框架,支持Linux和Windows操作系统,在linux上可以直接进行源码编译,得到动态库和静态库,直接链接就可以正常使用,在Windows上可以使用VC直接进行编译,非常便于调试。CppUnit的源码框架被运用到了Java和Python等语言中,使用非常广泛,熟悉了一种语言下的CppUnit使用方法,其他语言测试框架也不在话下,本文以cppunit-1.12.1为例进行演示和说明。

    一个例子

    Linux下CppUnit源码编译和安装

    • 解压源码文件到cppunit-1.12.1目录
    • cd cppunit-1.12.1
    • ./configure --prefix=安装路径(必须是绝对路径)
    • make 
    • make install

    编辑测试代码

    一共三个文件main.cpp、simpleTest.h、simpleTest.c,目录下文件的组织结构如下所示:

    三个文件的源码如下:

    //main.cpp文件
    
    #include "cppunit/TestResultCollector.h"
    #include "cppunit/TextOutputter.h"
    #include "cppunit/XmlOutputter.h"
    #include "cppunit/CompilerOutputter.h"
    #include "cppunit/TestResult.h"
    #include "cppunit/TestRunner.h"
    #include "cppunit/extensions/TestFactoryRegistry.h"
    #include <cstdlib>
    #include <ostream>
    
    int main()
    {
        CppUnit::TestResult r;
        CppUnit::TestResultCollector rc;
        r.addListener(&rc); // 准备好结果收集器
    
        CppUnit::TestRunner runner; // 定义执行实体
        runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("alltest").makeTest());
        runner.run(r); // 运行测试
    
        //CppUnit::TextOutputter o(&rc, std::cout);
        //o.write(); // 将结果输出
    	
    	//std::ofstream file;
    	//file.open("./UnitTest.xml");
    	//CppUnit::XmlOutputter xo(&rc, file);
    	//xo.write();
    	
    	CppUnit::CompilerOutputter co(&rc, std::cout);
    	co.write();
    
        return rc.wasSuccessful() ? 0 : -1;
    }
    
    //SimpleTest .h文件
    
    #include "cppunit/extensions/HelperMacros.h"
    
    class SimpleTest : public CppUnit::TestFixture
    {
        CPPUNIT_TEST_SUITE(SimpleTest);
        CPPUNIT_TEST(test1);
    	CPPUNIT_TEST(test2);
        CPPUNIT_TEST_SUITE_END();
    public:
    	void test1();
    	void test2();
    };
    
    //simpleTest.cpp文件
    
    #include "simpleTest.h"
    #include <string>
    #include <iostream>
    #include "cppunit/TestCase.h"
    #include "cppunit/TestAssert.h"
    
    CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(SimpleTest, "alltest");
    
    void SimpleTest::test2()
    {
        CPPUNIT_ASSERT(3 == 3);
    }
    
    void SimpleTest::test1()
    {
        CPPUNIT_ASSERT(2 == 2);
    }

    编译命令如下:

    g++ main.cpp simpleTest.cpp -o test -I /home/chusiyong/cppunit/install/include -L /home/chusiyong/cppunit/install/lib -Wl,-Bstatic -lcppunit -Wl,-Bdynamic -ldl  

    运行可执行文件,结果如下:

    OK (2)  

    表示所有用例都执行成功

    源码分析

    1.主要类的继承关系

    • Test相关类

     

      • Test类作为所有测试用例的基类,是一个抽象类,含有纯虚函数
      • Test类主要的方法是run方法
      • 采用Composition设计模式(类比文件和文件夹的设计方法)
      • TestComposition类主要是实现类名的处理,并提供start和end的处理(配合TestListener使用)
      • TestSuite类非常重要,里面可以包含多个Test类,使用Vector的方式保存
      • TestFixture类主要提供setUp和tearDown方法,用于运行测试用例前和测试用例后执行
      • TestLeaf类主要是实现Test类中的部分方法,在体现通用性的同时做安全措施,重写必要的virtual方法(实现Test类中模板方法中调用的函数),继承该类的子类只能是单个测试用例,不能包含子测试用例
      • TestCase类是主要的测试类,每一个TestCase表示一个测试用例
      • TestCaller类主要用来生成TestCase实例,将TestFixture类中的每一个测试方法,变成一个单独的TestCase实例(很重要),然后将TestCase实例加入到TestSuite中
    //TestComposite.h
    class CPPUNIT_API TestComposite : public Test
    {
    public:
      TestComposite( const std::string &name = "" );
      ~TestComposite();
      void run( TestResult *result );
      std::string getName() const;
    private:
      const std::string m_name;
    };
    
    //TestComposite.cpp
    void TestComposite::run( TestResult *result )
    {
      ...
      doRunChildTests( result );
      ...
    }
    
    void TestComposite::doRunChildTests( TestResult *controller)
                                           //关键方法,调用每一个子用例的run方法
    {
      int childCount = getChildTestCount();
      for ( int index =0; index < childCount; ++index )
      {
        if ( controller->shouldStop() )
          break;
    
        getChildTestAt( index )->run( controller );
      }
    }
    
    std::string TestComposite::getName() const //获取测试用例名称
    {
      return m_name;
    }
    
    //TestSuite.h
    class CPPUNIT_API TestSuite : public TestComposite
    {
    public:
      TestSuite( std::string name = "" );
      ~TestSuite();
      void addTest( Test *test ); //添加测试用例
      virtual void deleteContents(); //删除测试用例
      int getChildTestCount() const; //根据vector获取子用例个数
      Test *doGetChildTestAt( int index ) const;//根据index获取子用例对象
    private:
      CppUnitVector<Test *> m_tests; //保存子用例
    };
    
    //TestSuite.cpp
    void TestSuite::deleteContents() //删除所有测试用例
    {
      int childCount = getChildTestCount();
      for ( int index =0; index < childCount; ++index )
        delete getChildTestAt( index );
    
      m_tests.clear();
    }
    
    void TestSuite::addTest( Test *test ) //添加测试用例
    { 
      m_tests.push_back( test ); 
    }
    
    int TestSuite::getChildTestCount() const //获取子测试用例的个数
    {
      return m_tests.size();
    }
    
    Test *TestSuite::doGetChildTestAt( int index ) const//根据index获取子用例对象
    {
      return m_tests[index];
    }
    
    //TestLeaf.h 没有实现run方法,不能生成实例对象
    class CPPUNIT_API TestLeaf: public Test
    {
    public:
      int countTestCases() const;    //Test类中的checkIsValidIndex方法调用
      int getChildTestCount() const;//Test类中的checkIsValidIndex方法调用
      Test *doGetChildTestAt( int index ) const;//Test类中的getChildTestAt方法调用
    };
    
    //TestLeaf.cpp
    int TestLeaf::countTestCases() const
    {
      return 1;
    }
    
    int TestLeaf::getChildTestCount() const
    {
      return 0;
    }
    
    Test *TestLeaf::doGetChildTestAt( int index ) const
    {
      checkIsValidIndex( index );
      return NULL;    // never called, checkIsValidIndex() always throw.
    }
    
    //TestFixture.h
    class CPPUNIT_API TestFixture //接口
    {
    public:
      virtual ~TestFixture() {};
      virtual void setUp() {};//运行用例前调用
      virtual void tearDown() {};//运行用例后调用
    };
    
    //TestCase.h
    class CPPUNIT_API TestCase : public TestLeaf, public TestFixture
    {
    public:
        TestCase( const std::string &name );
        TestCase();
        ~TestCase();
        virtual void run(TestResult *result); //实现纯虚方法
        std::string getName() const; //获取用例名称
        virtual void runTest(); //子类实现
        
    private:
        TestCase( const TestCase &other ); 
        TestCase &operator=( const TestCase &other ); 
        
    private:
        const std::string m_name;
    };
    
    //TestCase.cpp
    //说明:运行测试用例的时候,是采用的保护性运行方式,保证一个用例执行失败后续的用例可以继续执行
    //采用try{...}catch{...}的模式,失败就抛异常,然后记录,继续执行
    void TestCase::run( TestResult *result )
    {
      result->startTest(this);
      if ( result->protect( TestCaseMethodFunctor( this, &TestCase::setUp ), this, "setUp() failed" ))
      {
        result->protect( TestCaseMethodFunctor( this, &TestCase::runTest ), this);
      }
    
      result->protect( TestCaseMethodFunctor( this, &TestCase::tearDown ), this, "tearDown() failed");
      result->endTest( this );
    }
    
      • TestCaseMethodFunctor类:函数对象,作用就是封装方法,便于使用
    class TestCaseMethodFunctor : public Functor
    {
    public:
      typedef void (TestCase::*Method)();
    
      TestCaseMethodFunctor( TestCase *target,
                             Method method )
         : m_target( target )
         , m_method( method )
      {
      }
    
      bool operator()() const //重载()操作符
      {
        (m_target->*m_method)(); //直接调用测试用例的地方
        return true;
      }
    
    private:
      TestCase *m_target;
      Method m_method;
    };
    
    template <class Fixture>
    class TestCaller : public TestCase
    { 
    public:
      TestCaller( std::string name, TestMethod test ) :
    	    TestCase( name ), 
    	    m_ownFixture( true ),
    	    m_fixture( new Fixture() ),
    	    m_test( test )
      {
      }
    
      TestCaller(std::string name, TestMethod test, Fixture& fixture) :
    	    TestCase( name ), 
    	    m_ownFixture( false ),
    	    m_fixture( &fixture ),
    	    m_test( test )
      {
      }
        
      TestCaller(std::string name, TestMethod test, Fixture* fixture) :
    	    TestCase( name ), 
    	    m_ownFixture( true ),
    	    m_fixture( fixture ),
    	    m_test( test )
      {
      }
        
      ~TestCaller() 
      {
        if (m_ownFixture)
          delete m_fixture;
      }
    
      void runTest() 
      {
    	(m_fixture->*m_test)(); //运行测试用例的地方
      }  
    
      void setUp()
      { 
      	m_fixture->setUp (); 
      }
    
      void tearDown()
      { 
    	  m_fixture->tearDown (); 
      }
    
      std::string toString() const
      { 
      	return "TestCaller " + getName(); 
      }
    
    private: 
      TestCaller( const TestCaller &other ); 
      TestCaller &operator =( const TestCaller &other );
    
    private:
      bool m_ownFixture;
      Fixture *m_fixture;   //new出来的测试对象,即TestCase
      typedef void (Fixture::*TestMethod)(); 
      TestMethod m_test;//Testcase中的一个测试方法
    };
    
    • TestListener相关类

      • TestListener类和TestResult类之间是采用观察者模式,TestResult类将测试用例的执行结果通知给TestListener类
      • TestListener类将保持的结果,通过OutPutter类显示出来
      • TestSuccessListener类主要作用是实现多线程安全
    class CPPUNIT_API TestListener
    {
    public:
      virtual ~TestListener() {}
      virtual void addFailure( const TestFailure & /*failure*/ ) {}
        //主要的函数,当测试用例执行失败时,调用该接口将结果保持到观察者实例中
    };
    
    //TestSuccessListener.h
    class CPPUNIT_API TestSuccessListener : public TestListener,
                                            public SynchronizedObject
    {
    public:
      TestSuccessListener( SynchronizationObject *syncObject = 0 );
      virtual ~TestSuccessListener();
      virtual void reset();
      void addFailure( const TestFailure &failure ); //添加失败信息
      virtual bool wasSuccessful() const; //判断执行结果
    
    private:
      bool m_success;
    };
    
    //TestSuccessListener.cpp
    void TestSuccessListener::addFailure( const TestFailure &failure )
    {
      ExclusiveZone zone( m_syncObject ); //多线程时的锁
      m_success = false;
    }
    
    bool TestSuccessListener::wasSuccessful() const
    {
      ExclusiveZone zone( m_syncObject );
      return m_success;
    }
    
    void TestSuccessListener::reset()
    {
      ExclusiveZone zone( m_syncObject );
      m_success = true;
    }
    
    //TestResultCollector.h
    class CPPUNIT_API TestResultCollector : public TestSuccessListener
    {
    public:
      TestResultCollector( SynchronizationObject *syncObject = 0 );
      virtual ~TestResultCollector();
    
      void addFailure( const TestFailure &failure );
    
      virtual void reset();
      
      virtual int testErrors() const;
      virtual int testFailures() const;
      virtual int testFailuresTotal() const;
    
      virtual const TestFailures& failures() const;
    
    protected:
      void freeFailures();
      
      typedef CppUnitDeque<Test *> Tests;
      Tests m_tests;
      
      typedef CppUnitDeque<TestFailure *> TestFailures;
      TestFailures m_failures;
      
      int m_testErrors;
    };
    
    //TestResultCollector.cpp
    void TestResultCollector::freeFailures() //释放所有错误信息
    {
      TestFailures::iterator itFailure = m_failures.begin();
      while ( itFailure != m_failures.end() )
        delete *itFailure++;
      m_failures.clear();
    }
    
    void TestResultCollector::reset() //将Listener的状态变成初始状态
    {
      TestSuccessListener::reset();
    
      ExclusiveZone zone( m_syncObject ); 
      freeFailures();
      m_testErrors = 0;
      m_tests.clear();
    }
    
    void TestResultCollector::addFailure( const TestFailure &failure )//添加错误信息
    {
      TestSuccessListener::addFailure( failure );
    
      ExclusiveZone zone( m_syncObject ); 
      if ( failure.isError() )
        ++m_testErrors;
      m_failures.push_back( failure.clone() );
    }
    
    int TestResultCollector::testFailuresTotal() const //返回错误信息的个数(包括error)
    {
      ExclusiveZone zone( m_syncObject ); 
      return m_failures.size();
    }
    
    int TestResultCollector::testFailures() const //返回失败用例的个数(不包括error)
    { 
      ExclusiveZone zone( m_syncObject ); 
      return m_failures.size() - m_testErrors;
    }
    
    //返回错误信息
    const TestResultCollector::TestFailures & TestResultCollector::failures() const
    { 
      ExclusiveZone zone( m_syncObject );
      return m_failures; 
    }
    
    //返回error的个数
    int TestResultCollector::testErrors() const
    { 
      ExclusiveZone zone( m_syncObject );
      return m_testErrors;
    }
    
      • TestFailure类:用于表示测试用例的执行结果,一个测试用例执行失败就会生成一个TestFailure类的实例
      • TestFailure可以表示用例执行失败,也可以表示error,二者的区别是:测试用例执行失败时抛出的异常是已知的,如果执行用例时抛出未知异常,就是error
    //TestFailure.cpp.h
    class CPPUNIT_API TestFailure 
    {
    public:
      TestFailure( Test *failedTest, Exception *thrownException, bool isError );
      virtual ~TestFailure ();
      virtual Test *failedTest() const;   //返回失败用例对象
      virtual Exception *thrownException() const; //返回抛出的对象
      virtual SourceLine sourceLine() const; //获取抛出异常的代码行号
      virtual bool isError() const; //判断是用例失败还是error
      virtual std::string failedTestName() const;//获取失败测试用例的名称
      virtual TestFailure *clone() const;//克隆
    
    protected:
      Test *m_failedTest;
      Exception *m_thrownException;
      bool m_isError;
    
    private: 
      TestFailure( const TestFailure &other ); 
      TestFailure &operator =( const TestFailure& other ); 
    };
    
    //TestFailure.cpp
    TestFailure::TestFailure( Test *failedTest, 
                              Exception *thrownException,
                              bool isError ) :
        m_failedTest( failedTest ), //失败的用例
        m_thrownException( thrownException ), //抛出的异常
        m_isError( isError )//是用例失败还是未知异常
    {
    }
    
    • 多线程安全同步机制
      • SynchronizedObject类起到一个域名的包装作用,防止名称空间被污染

      • SynchronizationObject类似一个基类,提供lock和unlock的接口,可以依据不同的平台进行继承实现互斥锁

      • ExclusiveZone类的作用是封装SynchronizationObject类,方便使用互斥锁,关键就是在构造函数中调用lock函数,析构函数中调用unlock函数,无需手动调用lock和unlock函数

    class CPPUNIT_API SynchronizedObject
    {
    public:
    
      class SynchronizationObject //实现互斥锁的基类
      {
        public:
          SynchronizationObject() {}
          virtual ~SynchronizationObject() {}
    
          virtual void lock() {}
          virtual void unlock() {}
      };
    
    
      SynchronizedObject( SynchronizationObject *syncObject =0 );
      virtual ~SynchronizedObject();
    
    protected:
        
      class ExclusiveZone //封装SynchronizationObject类的使用方式
      {
        SynchronizationObject *m_syncObject; 
    
      public:
        ExclusiveZone( SynchronizationObject *syncObject ) 
            : m_syncObject( syncObject ) 
        { 
          m_syncObject->lock(); //构造函数中调用lock函数
        }
    
        ~ExclusiveZone() 
        { 
          m_syncObject->unlock();//析构函数中调用unlock函数 
        }
      };
    
      virtual void setSynchronizationObject( SynchronizationObject *syncObject );
    
    protected:
      SynchronizationObject *m_syncObject;
    
    private:
      SynchronizedObject( const SynchronizedObject &copy );
      void operator =( const SynchronizedObject &copy );
    };
    
    • TestResult类,与TestListener类组成观察者模式,其中TestResult类是被观察者,TestListener类是观察者 
      • TestResult类的runTest方法是运行测试用例的源头,里面会执行测试用例,并将测试用例的执行结果通知给所有的观察者

      • TestResult类的runTest方法会调用每一个测试用例的run方法

      • TestResult类的关键代码如下:

    //TestResult.h
    class CPPUNIT_API TestResult : protected SynchronizedObject
    {
    public:
    
      TestResult( SynchronizationObject *syncObject = 0 );
      virtual ~TestResult();
    
      virtual void addListener( TestListener *listener );//添加测试用例
      virtual void removeListener( TestListener *listener );//移除测试用例
      
      virtual void addFailure( Test *test, Exception *e );//添加失败信息
    
      virtual void runTest( Test *test );//入口方法
    
    protected:
      void addFailure( const TestFailure &failure ); //将失败的消息通知给所有的观察者
      
    protected:
      typedef CppUnitDeque<TestListener *> TestListeners;
      TestListeners m_listeners;//保存所有的监听者
    };
    
    //TestResult.cpp
    void TestResult::addListener( TestListener *listener )//添加测试用例
    {
      ExclusiveZone zone( m_syncObject ); 
      m_listeners.push_back( listener );
    }
    
    void TestResult::removeListener ( TestListener *listener )//移除测试用例
    {
      ExclusiveZone zone( m_syncObject ); 
      removeFromSequence( m_listeners, listener );
    }
    
    void TestResult::runTest( Test *test )//入口方法
    {
      startTestRun( test );
      test->run( this ); 
      endTestRun( test );
    }
    
    void TestResult::addFailure( Test *test, Exception *e )//用例失败时被调用
    { 
      TestFailure failure( test, e, false );
      addFailure( failure );
    }
    
    void TestResult::addFailure( const TestFailure &failure )//将失败的消息通知给所有的观察者
    {
      ExclusiveZone zone( m_syncObject ); 
      for ( TestListeners::iterator it = m_listeners.begin();
            it != m_listeners.end(); 
            ++it )
        (*it)->addFailure( failure );
    }
    
    • OutPutter相关类

     

      • OutPutter是公共的基类,提供统一的接口
    class CPPUNIT_API Outputter
    {
    public:
      virtual ~Outputter() {}
    
      virtual void write() =0; //关键方法
    };
    
      • TextOutputter类:将执行结果按照文本模式打印出来,一般是输出到屏幕(一般在调试中使用)

      • XmlOutPutter类:将执行结果按照xml模式打印出来,一般是保存到xml文件中(一般在自动化中使用)

      • CompilerOutPutter类:将执行的结果以编译器兼容的模式打印出来,便于调试,一般不怎么使用

      • 总结:就是将TestResult类中的Failure信息以不同的格式输出

    2. 创建测试用例的相关类

    • 创建测试用例的相关类主要使用了工厂模式
    • 创建的具体过程使用了宏进行简化
    • 相关类如下
      • ConcretTestFixtureFactory类:用于创建测试用例对象
    class TestFixtureFactory
    {
    public:
      virtual TestFixture *makeFixture() =0; //用于创建具体测试用例的公共方法
    
      virtual ~TestFixtureFactory() {}
    };
    
    //使用工厂方法模式
    template<class TestFixtureType>
    class ConcretTestFixtureFactory : public CPPUNIT_NS::TestFixtureFactory
    {
      TestFixture *makeFixture()
      {
        return new TestFixtureType(); //根据具象的类型创建实例
      }
    };
    
      • TestSuiteBuilderContextBase类:用于将测试用例对象添加到suite中
    //TestSuiteBuilderContextBase.h
    class CPPUNIT_API TestSuiteBuilderContextBase
    {
    public:
      TestSuiteBuilderContextBase( TestSuite &suite,
                                   const TestNamer &namer,
                                   TestFixtureFactory &factory );
    
      virtual ~TestSuiteBuilderContextBase();
    
      void addTest( Test *test );
    
    protected:
      TestFixture *makeTestFixture() const; //创建测试用例
    
      TestSuite &m_suite; //用于保存测试用例的suite
      const TestNamer &m_namer; //保存suite的名称
      TestFixtureFactory &m_factory; //创建测试用例的工厂
    };
    
    //TestSuiteBuilderContextBase.cpp
    TestSuiteBuilderContextBase::TestSuiteBuilderContextBase( 
                                     TestSuite &suite,
                                     const TestNamer &namer,
                                     TestFixtureFactory &factory )
      : m_suite( suite )
      , m_namer( namer )
      , m_factory( factory )
    {//构造函数
    }
    
    TestFixture *TestSuiteBuilderContextBase::makeTestFixture() const 
    {
      return m_factory.makeFixture();
    }
    
    void TestSuiteBuilderContextBase::addTest( Test *test ) //添加用例到suite
    {
      m_suite.addTest( test );
    }
    
    • TestFactory类
    class CPPUNIT_API TestFactory 
    {
    public:
      virtual ~TestFactory() {}
      virtual Test* makeTest() = 0;
    };
    
    • TestSuiteFactory类:此处调用的TestCaseType::suite()返回的suite就是包含测试用例的suite
    template<class TestCaseType> 
      class TestSuiteFactory : public TestFactory
      {
      public:
        virtual Test *makeTest()
        {
          return TestCaseType::suite(); //关键方法,该方法的实现是宏定义
        }
      };
    
      • TestFactoryRegistry类:用于从TestFactoryRegistryList类中获取指定名称的TestFactoryRegistry实例
      • TestFactoryRegistryList类:单例类,根据名称保存所有的TestFactoryRegistry实例
      • AutoRegisterSuite类:封装TestSuiteFactory的注册方式

    3.框架入口类

    • TestRunner类是整个CppUnit的入口类,将TestSuite类、TestResult类以及TestListener类联合在一起,然后提供统一的入口方法,便于使用
    • TestListener实例包含在TestResult实例里面
    • 部分代码如下:
    //TestRunner.h
    class CPPUNIT_API TestRunner
    {
    public:
      TestRunner(  );
      virtual ~TestRunner();
      //将需要运行的测试用例添加进来
      virtual void addTest( Test *test ); 
      //运行指定的测试用例
      virtual void run( TestResult &controller, const std::string &testPath = "" );
    
    protected:
      //内部类,对suite进行了包装
      class CPPUNIT_API WrappingSuite : public TestSuite
      {
      public:
        WrappingSuite( const std::string &name = "All Tests" );
    
        int getChildTestCount() const;
    
        std::string getName() const;
    
        void run( TestResult *result );
    
      protected:
        Test *doGetChildTestAt( int index ) const;
    
        bool hasOnlyOneTest() const;
    
        Test *getUniqueChildTest() const;
      };
    
    protected:
      WrappingSuite *m_suite;
    
    private:
      TestRunner( const TestRunner &copy );
      void operator =( const TestRunner &copy );
    private:
    };
    
    //TestRunner.cpp
    void TestRunner::addTest( Test *test )
    {
      m_suite->addTest( test ); 
    }
    
    void TestRunner::run( TestResult &controller,
                     const std::string &testPath )
    {
      TestPath path = m_suite->resolveTestPath( testPath );
      Test *testToRun = path.getChildTest();
    
      controller.runTest( testToRun );
    }
    

     4.重要宏的解析

    • CPPUNIT_TEST_SUITE_NAMED_REGISTRATION
    CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(SimpleTest, "alltest");
    //展开后如下
    static CPPUNIT_NS::AutoRegisterSuite<SimpleTest> autoRegisterRegistry__12("alltest");
    
    • CPPUNIT_TEST_SUITE、CPPUNIT_TEST以及CPPUNIT_TEST_SUITE_END宏,这三个红必须配合使用,不能单独使用,用于声明需要运行的测试用例
    private:
    	//根据typeid(SimpleTest)为名称生成TestNamer类的实例,就是对名称的封装
    	static const CPPUNIT_NS::TestNamer &getTestNamer__()                    
    	{                                                                       
    		static CPPUNIT_NS::TestNamer testNamer(typeid(SimpleTest));         
    		return testNamer;                                                     
    	}          
    													
    public:                                                                   
    
    	//将测试用例添加到suite中
    	static void addTestsToSuite( CPPUNIT_NS::TestSuiteBuilderContextBase &baseContext ) 
    	{                                                                       
    		CPPUNIT_NS::TestSuiteBuilderContext<SimpleTest> context(baseContext)
    		context.addTest(( new CPPUNIT_NS::TestCaller<SimpleTest>(context.getTestNameFor( #testMethod), &SimpleTest::testMethod, context.makeFixture())))
    	}        
        
    	//对外接口,被TestSuiteFactory中的makeTest方法调用,返回一个完整的suite,等待被运行
    	static CPPUNIT_NS::TestSuite *suite()                                      
    	{                                                                          
    		const CPPUNIT_NS::TestNamer &namer = getTestNamer__();                   
    		std::auto_ptr<CPPUNIT_NS::TestSuite> suite(new CPPUNIT_NS::TestSuite(namer.getFixtureName()));             
    		CPPUNIT_NS::ConcretTestFixtureFactory<SimpleTest> factory;          
    		CPPUNIT_NS::TestSuiteBuilderContextBase context(*suite.get(), namer, factory );              
    		SimpleTest::addTestsToSuite( context );                             
    		return suite.release();                                                  
    	} 
    

     

  • 相关阅读:
    SVN还原项目到某一版本(转)
    C# Web Service 不使用服务引用直接调用方法(转)
    动态调用webservice时 ServiceDescriptionImporter类在vs2010无法引用的解决方法 (转)
    log4net示例2-日志输入存入Access(转)
    C# log4net 配置及使用详解--日志保存到文件和Access(转)
    未能解析引用的程序集......因为它对不在当前目标框架“.NETFramework,Version=v4.0,Profile=Client”中的 (转)
    Hello log4net——做一个实用好用的log4net的demo(转)
    JS移动客户端--触屏滑动事件
    js生成二维码实例
    触屏版类似刷新页面文本框获取焦点的同时弹出手机键盘的做法
  • 原文地址:https://www.cnblogs.com/chusiyong/p/11403681.html
Copyright © 2011-2022 走看看