diff options
| author | Baptiste Lepilleur <gaiacrtn@free.fr> | 2002-06-14 19:21:01 +0000 |
|---|---|---|
| committer | Baptiste Lepilleur <gaiacrtn@free.fr> | 2002-06-14 19:21:01 +0000 |
| commit | 73a038f1eaa268cec330d971fb550befec6f7798 (patch) | |
| tree | c3eba5d793e37413889acad5b0b9f70caf89b0f6 /examples/ClockerPlugIn | |
| parent | f39e160fba25476de7d41e2f19d756db7ee76dc7 (diff) | |
| download | cppunit-73a038f1eaa268cec330d971fb550befec6f7798.tar.gz | |
Include/cppunit/plugin/PlugInManager.
include/cppunit/plugin/PlugInManager.h:
* src/cppunit/PlugInManager.cpp: added two methods to use the plug-in
interface for Xml Outputter hooks.
* include/cppunit/plugin/TestPlugIn.h: added two methods to the plug-in
interface for Xml Outputter hooks.
* include/cppunit/plugin/TestPlugInAdapter.h:
* src/cppunit/plugin/TestPlugInAdapter.cpp: renamed TestPlugInDefaultImpl.
Added empty implementation for Xml outputter hook methods.
* include/cppunit/tools/StringTools.h:
* src/cppunit/tools/StringTools.cpp: added. Functions to manipulate string
(conversion, wrapping...)
* include/cppunit/tools/XmlElement.h:
* src/cppunit/XmlElement.cpp: renamed addNode() to addElement(). Added
methods to walk and modify XmlElement (for hook). Added documentation.
Use StringTools.
* include/cppunit/XmlOutputter.h:
* src/cppunit/XmlOutputter.cpp: added hook calls & management.
* include/cppunit/XmlOutputterHook.h:
* src/cppunit/XmlOutputterHook.cpp: added. Hook to customize XML output.
* src/DllPlugInTester/DllPlugInTester.cpp: call plug-in XmlOutputterHook
when writing XML output. Modified so that memory is freed before
unloading the test plug-in (caused crash when freeing the XmlDocument).
* examples/ReadMe.txt:
* examples/ClockerPlugIn/ReadMe.txt: added details about the plug-in
(usage, xml content...)
* examples/ClockerPlugIn/ClockerModel.h:
* examples/ClockerPlugIn/ClockerModel.cpp: extracted from ClockerListener.
Represents the test hierarchy and tracked time for each test.
* examples/ClockerPlugIn/ClockerListener.h:
* examples/ClockerPlugIn/ClockerListener.cpp: extracted test hierarchy
tracking to ClockerModel. Replaced the 'flat' view option with a 'text'
option to print the timed test tree to stdout.
* examples/ClockerPlugIn/ClockerPlugIn.cpp: updated to hook the XML
output and use the new classes.
* examples/ClockerPlugIn/ClockerXmlHook.h:
* examples/ClockerPlugIn/ClockerXmlHook.cpp: added. XmlOutputterHook to
includes the timed test hierarchy and test timing in the XML output.
* examples/cppunittest/XmlElementTest.h:
* examples/cppunittest/XmlElementTest.cpp: added new test cases.
* examples/cppunittest/XmlOutputterTest.h:
* examples/cppunittest/XmlOutputterTest.cpp: added tests for
XmlOutputterHook.
Diffstat (limited to 'examples/ClockerPlugIn')
| -rw-r--r-- | examples/ClockerPlugIn/ClockerListener.cpp | 130 | ||||
| -rw-r--r-- | examples/ClockerPlugIn/ClockerListener.h | 52 | ||||
| -rw-r--r-- | examples/ClockerPlugIn/ClockerModel.cpp | 145 | ||||
| -rw-r--r-- | examples/ClockerPlugIn/ClockerModel.h | 95 | ||||
| -rw-r--r-- | examples/ClockerPlugIn/ClockerPlugIn.cpp | 30 | ||||
| -rw-r--r-- | examples/ClockerPlugIn/ClockerPlugIn.dsp | 22 | ||||
| -rw-r--r-- | examples/ClockerPlugIn/ClockerXmlHook.cpp | 94 | ||||
| -rw-r--r-- | examples/ClockerPlugIn/ClockerXmlHook.h | 62 | ||||
| -rw-r--r-- | examples/ClockerPlugIn/ReadMe.txt | 42 |
9 files changed, 520 insertions, 152 deletions
diff --git a/examples/ClockerPlugIn/ClockerListener.cpp b/examples/ClockerPlugIn/ClockerListener.cpp index 9ac9c52..a93cd38 100644 --- a/examples/ClockerPlugIn/ClockerListener.cpp +++ b/examples/ClockerPlugIn/ClockerListener.cpp @@ -6,13 +6,14 @@ #include <cppunit/Test.h> #include <iostream> #include "ClockerListener.h" +#include "ClockerModel.h" #include <stdio.h> -ClockerListener::ClockerListener( bool flatten ) - : m_flatten( flatten ) - , m_testCount( 0 ) - , m_totalTestCaseTime( 0 ) +ClockerListener::ClockerListener( ClockerModel *model, + bool text ) + : m_model( model ) + , m_text( text ) { } @@ -26,121 +27,79 @@ void ClockerListener::startTestRun( CppUnit::Test *test, CppUnit::TestResult *eventManager ) { - m_tests.reserve( test->countTestCases() *2 ); + m_model->setExpectedTestCount( test->countTestCases() *2 ); } void -ClockerListener::startTest( CppUnit::Test *test ) -{ - enterTest( test, false ); - ++m_testCount; -} - - -void -ClockerListener::endTest( CppUnit::Test *test ) -{ - exitTest( test, false ); -} - - -void -ClockerListener::startSuite( CppUnit::Test *suite ) +ClockerListener::endTestRun( CppUnit::Test *test, + CppUnit::TestResult *eventManager ) { - enterTest( suite, true ); + if ( m_text ) + printStatistics(); } void -ClockerListener::endSuite( CppUnit::Test *suite ) +ClockerListener::startTest( CppUnit::Test *test ) { - exitTest( suite, true ); + m_model->enterTest( test, false ); } void -ClockerListener::endTestRun( CppUnit::Test *test, - CppUnit::TestResult *eventManager ) +ClockerListener::endTest( CppUnit::Test *test ) { - printStatistics(); + m_model->exitTest( test, false ); } void -ClockerListener::enterTest( CppUnit::Test *test, - bool isSuite ) +ClockerListener::startSuite( CppUnit::Test *suite ) { - m_currentPath.add( test ); - - int testIndex = m_tests.size(); - if ( !m_testIndexes.empty() ) - m_tests[ m_testIndexes.top() ].m_childIndexes.push_back( testIndex ); - m_testIndexes.push( testIndex ); - - TestInfo info; - info.m_timer.start(); - info.m_path = m_currentPath; - info.m_isSuite = isSuite; - - m_tests.push_back( info ); + m_model->enterTest( suite, true ); } void -ClockerListener::exitTest( CppUnit::Test *test, - bool isSuite ) +ClockerListener::endSuite( CppUnit::Test *suite ) { - m_tests[ m_testIndexes.top() ].m_timer.finish(); - if ( !isSuite ) - m_totalTestCaseTime += m_tests.back().m_timer.elapsedTime(); - - m_currentPath.up(); - m_testIndexes.pop(); + m_model->exitTest( suite, true ); } void ClockerListener::printStatistics() const { - printTest( m_tests[0], "" ); + printTest( 0, "" ); std::cout << std::endl; std::cout << "Total elapsed time: "; - printTestTime( m_tests[0].m_timer.elapsedTime() ); + printTime( m_model->totalElapsedTime() ); std::cout << ", average test case time: "; - double average = 0; - if ( m_testCount > 0 ) - average = m_totalTestCaseTime / m_testCount; - printTestTime( average ); + printTime( m_model->averageTestCaseTime() ); } void -ClockerListener::printTest( const TestInfo &info, +ClockerListener::printTest( int testIndex, const std::string &indentString ) const { std::string indent = indentString; const int indentLength = 3; - if ( !m_flatten ) - printTestIndent( indentString, indentLength ); - - printTestTime( info.m_timer.elapsedTime() ); - - if ( m_flatten ) - printFlattenedTestName( info ); - else - printTestName( info ); + printTestIndent( indentString, indentLength ); + printTime( m_model->testTimeFor( testIndex ) ); + std::cout << m_model->testPathFor( testIndex ).getChildTest()->getName(); std::cout << std::endl; - if ( info.m_childIndexes.empty() ) + if ( m_model->childCountFor( testIndex ) == 0 ) indent+= std::string( indentLength, ' ' ); else indent+= "|" + std::string( indentLength -1, ' ' ); - for ( int index =0; index < info.m_childIndexes.size(); ++index ) - printTest( m_tests[ info.m_childIndexes[ index ] ], indent ); + for ( int index =0; index < m_model->childCountFor( testIndex ); ++index ) + printTest( m_model->childAtFor( testIndex, index ), indent ); } @@ -158,36 +117,7 @@ ClockerListener::printTestIndent( const std::string &indent, void -ClockerListener::printTestTime( double elapsedSeconds ) const -{ - char buffer[320]; - const char *format; - if ( elapsedSeconds < 1 ) - format = "(%2.3fs) "; - else if ( elapsedSeconds < 10 ) - format = "(%3.2fs) "; - else if (elapsedSeconds < 100 ) - format = "(%4.1fs) "; - else - format = "(%5fs) "; - - ::sprintf( buffer, format, elapsedSeconds ); - - std::cout << buffer; -} - - -void -ClockerListener::printFlattenedTestName( const TestInfo &info ) const -{ - std::cout << info.m_path.toString(); - if ( info.m_isSuite ) - std::cout << "/"; -} - - -void -ClockerListener::printTestName( const TestInfo &info ) const +ClockerListener::printTime( double time ) const { - std::cout << info.m_path.getChildTest()->getName(); + std::cout << '(' << ClockerModel::timeStringFor( time ) << "s) "; } diff --git a/examples/ClockerPlugIn/ClockerListener.h b/examples/ClockerPlugIn/ClockerListener.h index b256380..e3c84e4 100644 --- a/examples/ClockerPlugIn/ClockerListener.h +++ b/examples/ClockerPlugIn/ClockerListener.h @@ -7,28 +7,25 @@ #define CLOCKERLISTENER_H #include <cppunit/TestListener.h> -#include <cppunit/TestPath.h> -#include <stack> -#include <vector> -#ifdef CLOCKER_USE_WINNTTIMER -#include "WinNtTimer.h" -typedef WinNtTimer Timer; -#else -#include "Timer.h" -#endif +class ClockerModel; + /// TestListener that prints a flatten or hierarchical view of the test tree. class ClockerListener : public CppUnit::TestListener { public: - ClockerListener( bool flatten ); + ClockerListener( ClockerModel *model, + bool text ); virtual ~ClockerListener(); void startTestRun( CppUnit::Test *test, CppUnit::TestResult *eventManager ); + void endTestRun( CppUnit::Test *test, + CppUnit::TestResult *eventManager ); + void startTest( CppUnit::Test *test ); void endTest( CppUnit::Test *test ); @@ -37,37 +34,16 @@ public: void endSuite( CppUnit::Test *suite ); - void endTestRun( CppUnit::Test *test, - CppUnit::TestResult *eventManager ); - private: - struct TestInfo - { - CppUnit::TestPath m_path; - Timer m_timer; - bool m_isSuite; - std::vector<int> m_childIndexes; - }; - - void enterTest( CppUnit::Test *test, - bool isSuite ); - - void exitTest( CppUnit::Test *test, - bool isSuite ); - void printStatistics() const; - void printTest( const TestInfo &info, + void printTest( int testIndex, const std::string &indentString ) const; void printTestIndent( const std::string &indent, const int indentLength ) const; - void printTestTime( double elapsedSeconds ) const; - - void printFlattenedTestName( const TestInfo &info ) const; - - void printTestName( const TestInfo &info ) const; + void printTime( double time ) const; /// Prevents the use of the copy constructor. ClockerListener( const ClockerListener &other ); @@ -76,14 +52,8 @@ private: void operator =( const ClockerListener &other ); private: - bool m_flatten; - CppUnit::TestPath m_currentPath; - - int m_testCount; - double m_totalTestCaseTime; - - std::stack<int> m_testIndexes; - std::vector<TestInfo> m_tests; + ClockerModel *m_model; + bool m_text; }; diff --git a/examples/ClockerPlugIn/ClockerModel.cpp b/examples/ClockerPlugIn/ClockerModel.cpp new file mode 100644 index 0000000..60e87ad --- /dev/null +++ b/examples/ClockerPlugIn/ClockerModel.cpp @@ -0,0 +1,145 @@ +// ////////////////////////////////////////////////////////////////////////// +// Implementation file ClockerModel.cpp for class ClockerModel +// (c)Copyright 2000, Baptiste Lepilleur. +// Created: 2002/06/14 +// ////////////////////////////////////////////////////////////////////////// +#include "ClockerModel.h" + + +ClockerModel::ClockerModel() + : m_testCaseCount( 0 ) + , m_totalTestCaseTime( 0 ) +{ +} + + +ClockerModel::~ClockerModel() +{ +} + + +void +ClockerModel::setExpectedTestCount( int count ) +{ + m_tests.reserve( count ); +} + + +void +ClockerModel::enterTest( CppUnit::Test *test, + bool isSuite ) +{ + m_currentPath.add( test ); + + int testIndex = m_tests.size(); + if ( !m_testIndexes.empty() ) + m_tests[ m_testIndexes.top() ].m_childIndexes.push_back( testIndex ); + m_testIndexes.push( testIndex ); + m_testToIndexes.insert( TestToIndexes::value_type( test, testIndex ) ); + + TestInfo info; + info.m_timer.start(); + info.m_path = m_currentPath; + info.m_isSuite = isSuite; + + m_tests.push_back( info ); + + if ( !isSuite ) + ++m_testCaseCount; +} + + +void +ClockerModel::exitTest( CppUnit::Test *test, + bool isSuite ) +{ + m_tests[ m_testIndexes.top() ].m_timer.finish(); + if ( !isSuite ) + m_totalTestCaseTime += m_tests.back().m_timer.elapsedTime(); + + m_currentPath.up(); + m_testIndexes.pop(); +} + + +double +ClockerModel::totalElapsedTime() const +{ + return m_tests[0].m_timer.elapsedTime(); +} + + +double +ClockerModel::averageTestCaseTime() const +{ + double average = 0; + if ( m_testCaseCount > 0 ) + average = m_totalTestCaseTime / m_testCaseCount; + return average; +} + + +double +ClockerModel::testTimeFor( int testIndex ) const +{ + return m_tests[ testIndex ].m_timer.elapsedTime(); +} + + +std::string +ClockerModel::timeStringFor( double time ) +{ + char buffer[320]; + const char *format; + if ( time < 1 ) + format = "%2.3f"; + else if ( time < 10 ) + format = "%3.2f"; + else if (time < 100 ) + format = "%4.1f"; + else + format = "%6f"; + + ::sprintf( buffer, format, time ); + + return buffer; +} + + +bool +ClockerModel::isSuite( int testIndex ) const +{ + return m_tests[ testIndex ].m_isSuite; +} + + +const CppUnit::TestPath & +ClockerModel::testPathFor( int testIndex ) const +{ + return m_tests[ testIndex ].m_path; +} + + +int +ClockerModel::indexOf( CppUnit::Test *test ) const +{ + TestToIndexes::const_iterator itFound = m_testToIndexes.find( test ); + if ( itFound != m_testToIndexes.end() ) + return itFound->second; + return -1; +} + + +int +ClockerModel::childCountFor( int testIndex ) const +{ + return m_tests[ testIndex ].m_childIndexes.size(); +} + + +int +ClockerModel::childAtFor( int testIndex, + int chidIndex ) const +{ + return m_tests[ testIndex ].m_childIndexes[ chidIndex ]; +} diff --git a/examples/ClockerPlugIn/ClockerModel.h b/examples/ClockerPlugIn/ClockerModel.h new file mode 100644 index 0000000..c61a4b7 --- /dev/null +++ b/examples/ClockerPlugIn/ClockerModel.h @@ -0,0 +1,95 @@ +// ////////////////////////////////////////////////////////////////////////// +// Header file ClockerModel.h for class ClockerModel +// (c)Copyright 2000, Baptiste Lepilleur. +// Created: 2002/06/14 +// ////////////////////////////////////////////////////////////////////////// +#ifndef CLOCKERMODEL_H +#define CLOCKERMODEL_H + +#include <cppunit/TestPath.h> +#include <map> +#include <stack> +#include <string> +#include <vector> + +#ifdef CLOCKER_USE_WINNTTIMER +#include "WinNtTimer.h" +typedef WinNtTimer Timer; +#else +#include "Timer.h" +#endif + + +/// Model that represents test timing. +class ClockerModel +{ +public: + /*! Constructs a ClockerModel object. + */ + ClockerModel(); + + /// Destructor. + virtual ~ClockerModel(); + + void setExpectedTestCount( int count ); + + void enterTest( CppUnit::Test *test, + bool isSuite ); + + void exitTest( CppUnit::Test *test, + bool isSuite ); + + double totalElapsedTime() const; + + double averageTestCaseTime() const; + + double testTimeFor( CppUnit::Test *test ) const; + + double testTimeFor( int testIndex ) const; + + static std::string timeStringFor( double time ); + + bool isSuite( int testIndex ) const; + + const CppUnit::TestPath &testPathFor( int testIndex ) const; + + // -1 is none + int indexOf( CppUnit::Test *test ) const; + + int childCountFor( int testIndex ) const; + + int childAtFor( int testIndex, + int chidIndex ) const; + +private: + struct TestInfo + { + CppUnit::TestPath m_path; + Timer m_timer; + bool m_isSuite; + std::vector<int> m_childIndexes; + }; + + /// Prevents the use of the copy constructor. + ClockerModel( const ClockerModel &other ); + + /// Prevents the use of the copy operator. + void operator =( const ClockerModel &other ); + +private: + CppUnit::TestPath m_currentPath; + + int m_testCaseCount; + double m_totalTestCaseTime; + + typedef std::map<CppUnit::Test *, int> TestToIndexes; + + TestToIndexes m_testToIndexes; + std::stack<int> m_testIndexes; + std::vector<TestInfo> m_tests; +}; + + + + +#endif // CLOCKERMODEL_H diff --git a/examples/ClockerPlugIn/ClockerPlugIn.cpp b/examples/ClockerPlugIn/ClockerPlugIn.cpp index 8943629..dbdd672 100644 --- a/examples/ClockerPlugIn/ClockerPlugIn.cpp +++ b/examples/ClockerPlugIn/ClockerPlugIn.cpp @@ -1,6 +1,9 @@ #include <cppunit/TestResult.h> +#include <cppunit/XmlOutputter.h> #include <cppunit/plugin/TestPlugIn.h> +#include "ClockerXmlHook.h" #include "ClockerListener.h" +#include "ClockerModel.h" @@ -9,23 +12,29 @@ class ClockerPlugIn : public CppUnitTestPlugIn public: ClockerPlugIn() : m_dumper( NULL ) + , m_model( NULL ) + , m_xmlHook( NULL ) { } ~ClockerPlugIn() { delete m_dumper; + delete m_model; + delete m_xmlHook; } void initialize( CppUnit::TestFactoryRegistry *registry, const CppUnit::Parameters ¶meters ) { - bool flatten = false; - if ( parameters.size() > 0 && parameters[0] == "flat" ) - flatten = true; + bool text = false; + if ( parameters.size() > 0 && parameters[0] == "text" ) + text = true; - m_dumper = new ClockerListener( flatten ); + m_model = new ClockerModel(); + m_dumper = new ClockerListener( m_model, text ); + m_xmlHook = new ClockerXmlHook( m_model ); } @@ -41,12 +50,25 @@ public: } + void addXmlOutputterHooks( CppUnit::XmlOutputter *outputter ) + { + outputter->addHook( m_xmlHook ); + } + + + void removeXmlOutputterHooks() + { + } + + void uninitialize( CppUnit::TestFactoryRegistry *registry ) { } private: ClockerListener *m_dumper; + ClockerModel *m_model; + ClockerXmlHook *m_xmlHook; }; diff --git a/examples/ClockerPlugIn/ClockerPlugIn.dsp b/examples/ClockerPlugIn/ClockerPlugIn.dsp index 98e206a..8d865e1 100644 --- a/examples/ClockerPlugIn/ClockerPlugIn.dsp +++ b/examples/ClockerPlugIn/ClockerPlugIn.dsp @@ -44,7 +44,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CLOCKERPLUGIN_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MDd /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CPPUNIT_DLL" /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CPPUNIT_DLL" /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 @@ -130,14 +130,34 @@ SOURCE=.\ClockerListener.h # End Source File # Begin Source File +SOURCE=.\ClockerModel.cpp +# End Source File +# Begin Source File + +SOURCE=.\ClockerModel.h +# End Source File +# Begin Source File + SOURCE=.\ClockerPlugIn.cpp # End Source File # Begin Source File +SOURCE=.\ClockerXmlHook.cpp +# End Source File +# Begin Source File + +SOURCE=.\ClockerXmlHook.h +# End Source File +# Begin Source File + SOURCE=.\Makefile.am # End Source File # Begin Source File +SOURCE=.\ReadMe.txt +# End Source File +# Begin Source File + SOURCE=.\Timer.cpp !IF "$(CFG)" == "ClockerPlugIn - Win32 Release" diff --git a/examples/ClockerPlugIn/ClockerXmlHook.cpp b/examples/ClockerPlugIn/ClockerXmlHook.cpp new file mode 100644 index 0000000..445b868 --- /dev/null +++ b/examples/ClockerPlugIn/ClockerXmlHook.cpp @@ -0,0 +1,94 @@ +// ////////////////////////////////////////////////////////////////////////// +// Implementation file ClockerXmlHook.cpp for class ClockerXmlHook +// (c)Copyright 2000, Baptiste Lepilleur. +// Created: 2002/06/14 +// ////////////////////////////////////////////////////////////////////////// + +#include <cppunit/Test.h> +#include <cppunit/tools/XmlElement.h> +#include "ClockerModel.h" +#include "ClockerXmlHook.h" + + +ClockerXmlHook::ClockerXmlHook( ClockerModel *model ) + : m_model( model ) +{ +} + + +ClockerXmlHook::~ClockerXmlHook() +{ +} + + +void +ClockerXmlHook::endDocument( CppUnit::XmlDocument *document, + CppUnit::XmlElement *rootNode ) +{ + CppUnit::XmlElement *testTreeElement = new CppUnit::XmlElement( "TimedTestTree" ); + rootNode->addElement( testTreeElement ); + + addTimedTest( testTreeElement, 0 ); +} + + +void +ClockerXmlHook::addTimedTest( CppUnit::XmlElement *parentElement, + int testIndex ) +{ + std::string elementName = m_model->isSuite( testIndex ) ? "TimedSuite" : "TimedTest"; + CppUnit::XmlElement *testElement = new CppUnit::XmlElement( elementName ); + parentElement->addElement( testElement ); + testElement->addAttribute( "id", testIndex ); + + const CppUnit::TestPath &path = m_model->testPathFor( testIndex ); + testElement->addElement( new CppUnit::XmlElement( "Name", + path.getChildTest()->getName() ) ); + testElement->addElement( new CppUnit::XmlElement( "TestPath", path.toString() ) ); + testElement->addElement( new CppUnit::XmlElement( "Time", + ClockerModel::timeStringFor( + m_model->testTimeFor( testIndex ) ) ) ); + + if ( m_model->isSuite( testIndex ) ) + { + for ( int childIndex =0; childIndex < m_model->childCountFor( testIndex ); ++childIndex ) + addTimedTest( testElement, m_model->childAtFor( testIndex, childIndex ) ); + } +} + + +void +ClockerXmlHook::failTestAdded( CppUnit::XmlDocument *document, + CppUnit::XmlElement *testNode, + CppUnit::Test *test, + CppUnit::TestFailure *failure ) +{ + successfulTestAdded( document, testNode, test ); +} + + +void +ClockerXmlHook::successfulTestAdded( CppUnit::XmlDocument *document, + CppUnit::XmlElement *testNode, + CppUnit::Test *test ) +{ + int testIndex = m_model->indexOf( test ); + double time = (testIndex >= 0) ? m_model->testTimeFor( testIndex ) : 0.0; + const CppUnit::TestPath &path = m_model->testPathFor( testIndex ); + testNode->addElement( new CppUnit::XmlElement( "TestPath", path.toString() ) ); + testNode->addElement( new CppUnit::XmlElement( "Time", + ClockerModel::timeStringFor( time ) ) ); +} + + +void +ClockerXmlHook::statisticsAdded( CppUnit::XmlDocument *document, + CppUnit::XmlElement *statisticsNode ) +{ + statisticsNode->addElement( + new CppUnit::XmlElement( "TotalElapsedTime", + ClockerModel::timeStringFor( m_model->totalElapsedTime() ) ) ); + statisticsNode->addElement( + new CppUnit::XmlElement( "AverageTestCaseTime", + ClockerModel::timeStringFor( m_model->averageTestCaseTime() ) ) ); +} diff --git a/examples/ClockerPlugIn/ClockerXmlHook.h b/examples/ClockerPlugIn/ClockerXmlHook.h new file mode 100644 index 0000000..fa86245 --- /dev/null +++ b/examples/ClockerPlugIn/ClockerXmlHook.h @@ -0,0 +1,62 @@ +// ////////////////////////////////////////////////////////////////////////// +// Header file ClockerXmlHook.h for class ClockerXmlHook +// (c)Copyright 2000, Baptiste Lepilleur. +// Created: 2002/06/14 +// ////////////////////////////////////////////////////////////////////////// +#ifndef CLOCKERXMLHOOK_H +#define CLOCKERXMLHOOK_H + +#include <cppunit/XmlOutputterHook.h> + +class ClockerModel; + + + +/// XML output hook to add test timing and test hierarchy timing. +class ClockerXmlHook : public CppUnit::XmlOutputterHook +{ +public: + /*! Constructs a ClockerXmlHook object. + */ + ClockerXmlHook( ClockerModel *model ); + + /// Destructor. + virtual ~ClockerXmlHook(); + + void endDocument( CppUnit::XmlDocument *document, + CppUnit::XmlElement *rootNode ); + + void failTestAdded( CppUnit::XmlDocument *document, + CppUnit::XmlElement *testNode, + CppUnit::Test *test, + CppUnit::TestFailure *failure ); + + void successfulTestAdded( CppUnit::XmlDocument *document, + CppUnit::XmlElement *testNode, + CppUnit::Test *test ); + + void statisticsAdded( CppUnit::XmlDocument *document, + CppUnit::XmlElement *statisticsNode ); + +private: + /// Prevents the use of the copy constructor. + ClockerXmlHook( const ClockerXmlHook &other ); + + /// Prevents the use of the copy operator. + void operator =( const ClockerXmlHook &other ); + + void addTimedTest( CppUnit::XmlElement *parentElement, + int testIndex ); + +private: + ClockerModel *m_model; +}; + + + +// Inlines methods for ClockerXmlHook: +// ----------------------------------- + + + +#endif // CLOCKERXMLHOOK_H diff --git a/examples/ClockerPlugIn/ReadMe.txt b/examples/ClockerPlugIn/ReadMe.txt index 6893fc6..57e4fc5 100644 --- a/examples/ClockerPlugIn/ReadMe.txt +++ b/examples/ClockerPlugIn/ReadMe.txt @@ -1,14 +1,44 @@ -A plug-ins that track tests and test suites running time. A demonstration of TestListener and -test plug-in. +A test plug-ins that track tests and test suites running time. It demonstrates +TestListener, TestPlugIn, and XmlOutputterHook. -Don't use this to profile your application, use a Profiler. +Both suite and test case times are tracked. The plug-in include in the XML +output the TestPath of each test cases and its tracked time. -Usage: +The timed test hierarchy is also included in the XML output. This way it is +possible to see the time each suite takes to run. -The plug-in accept the option "flat" to generate a flattened view of the test tree. + + +* Usage: + +Just add this plug-in to DllPlugInTester command line. It will add a test +listener to track test time, and add a hook to the XmlOutputter to include +test time to the XmlOutput. + +If the option "text" is passed to the plug-in, the timed test tree will be +printed to stdout. DllPlugInRunnerd.exe ClockerPlugInd.dll or -DllPlugInRunnerd.exe ClockerPlugInd.dll=flat +DllPlugInRunnerd.exe ClockerPlugInd.dll=text + +* Example: + +DllPlugInTesterd_dll.exe -x timed.xml ClockerPlugInd.dll CppUnitTestPlugInd.dll + +Will track time of all tests contains in CppUnitTestPlugInd.dll and save the +result in timed.xml. + +* Notes: + +The id of the <TimedTestTree> are different than those of the +<SuccessfulTests> and <FailedTests> trees. You can use the <TestPath> to +cross-reference the datas. + +* Remarks: +You may want to review ClockerModel before using this plug-in for serious +purpose, add timing based on the process cpu time. +A version is provided for NT that use the main thread cpu time. This is an issue +if the test cases are multithreaded. |
