|
Futur Membre du Club
Inscription : mars 2007 Messages : 76 Détails du profil  Informations personnelles : Âge : 27 Localisation : France, Finistère (Bretagne) Informations forums :
Inscription : mars 2007 Messages : 76 Points : 17 Points : 17
|
Voici le code pour avoir le temps d'execution avec CppUnit. Ce code fonctionne actuellement seulement sur Linux. Mais pour faire fonctionner ce code Windows, il suffit de réécrire la classe Timer.
Classe Timer
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #ifndef TIMER_H
#define TIMER_H
#include <cstdio>
#include <sys/time.h>
/// A Timer.
class Timer
{
public:
void start();
void finish();
double elapsedTime() const;
private:
struct timeval _beginTime;
double _elapsedTime;
};
#endif // TIMER_H |
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include "Timer.hpp"
void Timer::start()
{
gettimeofday(&_beginTime, NULL);
}
void Timer::finish()
{
struct timeval endTime;
gettimeofday(&endTime,NULL);
double dTime1 = _beginTime.tv_sec+(_beginTime.tv_usec/1000000.0);
double dTime2 = endTime.tv_sec+(endTime.tv_usec/1000000.0);
_elapsedTime = dTime2 - dTime1;
}
double Timer::elapsedTime() const
{
return _elapsedTime;
} |
Classe ClockerModel
Classe permettant de stocker les temps d'execution des tests unitaires
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
#ifndef CLOCKERMODEL_H
#define CLOCKERMODEL_H
#include <cppunit/TestPath.h>
#include <cppunit/portability/CppUnitVector.h>
#include <cppunit/portability/CppUnitMap.h>
#include <cppunit/portability/CppUnitStack.h>
#include <cstdio>
#include <string>
#include "Timer.hpp"
/// Model that represents test timing.
class ClockerModel
{
public:
/*! Constructs a ClockerModel object.
*/
ClockerModel();
/// Destructor.
virtual ~ClockerModel();
void setExpectedTestCount( int count );
void enterTest( CPPUNIT_NS::Test *test,
bool isSuite );
void exitTest( CPPUNIT_NS::Test *test,
bool isSuite );
double totalElapsedTime() const;
double averageTestCaseTime() const;
double testTimeFor( CPPUNIT_NS::Test *test ) const;
double testTimeFor( int testIndex ) const;
static std::string timeStringFor( double time );
bool isSuite( int testIndex ) const;
const CPPUNIT_NS::TestPath &testPathFor( int testIndex ) const;
// -1 is none
int indexOf( CPPUNIT_NS::Test *test ) const;
int childCountFor( int testIndex ) const;
int childAtFor( int testIndex,
int chidIndex ) const;
private:
struct TestInfo
{
CPPUNIT_NS::TestPath m_path;
Timer m_timer;
bool m_isSuite;
CppUnitVector<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_NS::TestPath m_currentPath;
int m_testCaseCount;
double m_totalTestCaseTime;
typedef CppUnitMap<CPPUNIT_NS::Test *, int> TestToIndexes;
TestToIndexes m_testToIndexes;
CppUnitStack<int> m_testIndexes;
CppUnitVector<TestInfo> m_tests;
};
#endif // CLOCKERMODEL_H |
Classe ClockerListener
Classe permettant de mesurer les temps d'execution des tests unitaires
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #ifndef CLOCKERLISTENER_H
#define CLOCKERLISTENER_H
#include <cppunit/TestListener.h>
class ClockerModel;
class ClockerListener : public CPPUNIT_NS::TestListener
{
public:
ClockerListener( ClockerModel *model,
bool text );
virtual ~ClockerListener();
void startTestRun( CPPUNIT_NS::Test *test,
CPPUNIT_NS::TestResult *eventManager );
void endTestRun( CPPUNIT_NS::Test *test,
CPPUNIT_NS::TestResult *eventManager );
void startTest( CPPUNIT_NS::Test *test );
void endTest( CPPUNIT_NS::Test *test );
void startSuite( CPPUNIT_NS::Test *suite );
void endSuite( CPPUNIT_NS::Test *suite );
private:
void printStatistics() const;
void printTest( int testIndex,
const std::string &indentString ) const;
void printTestIndent( const std::string &indent,
const int indentLength ) const;
void printTime( double time ) const;
/// Prevents the use of the copy constructor.
ClockerListener( const ClockerListener &other );
/// Prevents the use of the copy operator.
void operator =( const ClockerListener &other );
private:
ClockerModel *m_model;
bool m_text;
};
#endif // CLOCKERLISTENER_H |
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| #include <cppunit/Test.h>
#include <cppunit/portability/Stream.h>
#include "ClockerListener.hpp"
#include "ClockerModel.hpp"
#include <stdio.h>
ClockerListener::ClockerListener( ClockerModel *model,
bool text )
: m_model( model )
, m_text( text )
{
}
ClockerListener::~ClockerListener()
{
}
void
ClockerListener::startTestRun( CPPUNIT_NS::Test *test,
CPPUNIT_NS::TestResult *eventManager )
{
m_model->setExpectedTestCount( test->countTestCases() *2 );
}
void
ClockerListener::endTestRun( CPPUNIT_NS::Test *test,
CPPUNIT_NS::TestResult *eventManager )
{
if ( m_text )
printStatistics();
}
void
ClockerListener::startTest( CPPUNIT_NS::Test *test )
{
m_model->enterTest( test, false );
}
void
ClockerListener::endTest( CPPUNIT_NS::Test *test )
{
m_model->exitTest( test, false );
}
void
ClockerListener::startSuite( CPPUNIT_NS::Test *suite )
{
m_model->enterTest( suite, true );
}
void
ClockerListener::endSuite( CPPUNIT_NS::Test *suite )
{
m_model->exitTest( suite, true );
}
void
ClockerListener::printStatistics() const
{
printTest( 0, "" );
CPPUNIT_NS::stdCOut() << "\n";
CPPUNIT_NS::stdCOut() << "Total elapsed time: ";
printTime( m_model->totalElapsedTime() );
CPPUNIT_NS::stdCOut() << ", average test case time: ";
printTime( m_model->averageTestCaseTime() );
}
void
ClockerListener::printTest( int testIndex,
const std::string &indentString ) const
{
std::string indent = indentString;
const int indentLength = 3;
printTestIndent( indentString, indentLength );
printTime( m_model->testTimeFor( testIndex ) );
CPPUNIT_NS::stdCOut() << m_model->testPathFor( testIndex ).getChildTest()->getName();
CPPUNIT_NS::stdCOut() << "\n";
if ( m_model->childCountFor( testIndex ) == 0 )
indent+= std::string( indentLength, ' ' );
else
indent+= "|" + std::string( indentLength -1, ' ' );
for ( int index =0; index < m_model->childCountFor( testIndex ); ++index )
printTest( m_model->childAtFor( testIndex, index ), indent );
}
void
ClockerListener::printTestIndent( const std::string &indent,
const int indentLength ) const
{
if ( indent.empty() )
return;
CPPUNIT_NS::stdCOut() << " ";
CPPUNIT_NS::stdCOut() << indent.substr( 0, indent.length() - indentLength ) ;
CPPUNIT_NS::stdCOut() << "+" << std::string( indentLength -1, '-' );
}
void
ClockerListener::printTime( double time ) const
{
CPPUNIT_NS::stdCOut() << '(' << ClockerModel::timeStringFor( time ) << "s) ";
} |
Classe ClockerXmlHook
Classe permettant de rajouter les temps d'execution au fichier XML
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #ifndef CLOCKERXMLHOOK_H
#define CLOCKERXMLHOOK_H
#include <cppunit/XmlOutputterHook.h>
class ClockerModel;
class ClockerXmlHook : public CPPUNIT_NS::XmlOutputterHook
{
public:
/*! Constructs a ClockerXmlHook object.
*/
ClockerXmlHook( ClockerModel *model );
/// Destructor.
virtual ~ClockerXmlHook();
void endDocument( CPPUNIT_NS::XmlDocument *document );
void failTestAdded( CPPUNIT_NS::XmlDocument *document,
CPPUNIT_NS::XmlElement *testElement,
CPPUNIT_NS::Test *test,
CPPUNIT_NS::TestFailure *failure );
void successfulTestAdded( CPPUNIT_NS::XmlDocument *document,
CPPUNIT_NS::XmlElement *testElement,
CPPUNIT_NS::Test *test );
void statisticsAdded( CPPUNIT_NS::XmlDocument *document,
CPPUNIT_NS::XmlElement *statisticsElement );
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_NS::XmlElement *parentElement,
int testIndex );
private:
ClockerModel *m_model;
};
#endif // CLOCKERXMLHOOK_H |
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| #include <cppunit/Test.h>
#include <cppunit/tools/XmlDocument.h>
#include <cppunit/tools/XmlElement.h>
#include "ClockerModel.hpp"
#include "ClockerXmlHook.hpp"
ClockerXmlHook::ClockerXmlHook( ClockerModel *model )
: m_model( model )
{
}
ClockerXmlHook::~ClockerXmlHook()
{
}
void
ClockerXmlHook::endDocument( CPPUNIT_NS::XmlDocument *document )
{
CPPUNIT_NS::XmlElement *testTreeElement = new CPPUNIT_NS::XmlElement( "TimedTestTree" );
document->rootElement().addElement( testTreeElement );
addTimedTest( testTreeElement, 0 );
}
void
ClockerXmlHook::addTimedTest( CPPUNIT_NS::XmlElement *parentElement,
int testIndex )
{
std::string elementName = m_model->isSuite( testIndex ) ? "TimedSuite" : "TimedTest";
CPPUNIT_NS::XmlElement *testElement = new CPPUNIT_NS::XmlElement( elementName );
parentElement->addElement( testElement );
testElement->addAttribute( "id", testIndex );
const CPPUNIT_NS::TestPath &path = m_model->testPathFor( testIndex );
testElement->addElement( new CPPUNIT_NS::XmlElement( "Name",
path.getChildTest()->getName() ) );
testElement->addElement( new CPPUNIT_NS::XmlElement( "TestPath", path.toString() ) );
testElement->addElement( new CPPUNIT_NS::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_NS::XmlDocument *document,
CPPUNIT_NS::XmlElement *testElement,
CPPUNIT_NS::Test *test,
CPPUNIT_NS::TestFailure *failure )
{
successfulTestAdded( document, testElement, test );
}
void
ClockerXmlHook::successfulTestAdded( CPPUNIT_NS::XmlDocument *document,
CPPUNIT_NS::XmlElement *testElement,
CPPUNIT_NS::Test *test )
{
int testIndex = m_model->indexOf( test );
double time = (testIndex >= 0) ? m_model->testTimeFor( testIndex ) : 0.0;
const CPPUNIT_NS::TestPath &path = m_model->testPathFor( testIndex );
testElement->addElement( new CPPUNIT_NS::XmlElement( "TestPath", path.toString() ) );
testElement->addElement( new CPPUNIT_NS::XmlElement( "Time",
ClockerModel::timeStringFor( time ) ) );
}
void
ClockerXmlHook::statisticsAdded( CPPUNIT_NS::XmlDocument *document,
CPPUNIT_NS::XmlElement *statisticsElement )
{
statisticsElement->addElement(
new CPPUNIT_NS::XmlElement( "TotalElapsedTime",
ClockerModel::timeStringFor( m_model->totalElapsedTime() ) ) );
statisticsElement->addElement(
new CPPUNIT_NS::XmlElement( "AverageTestCaseTime",
ClockerModel::timeStringFor( m_model->averageTestCaseTime() ) ) );
} |
Et enfin la classe Main
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #include <cppunit/BriefTestProgressListener.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/XmlOutputter.h>
#include <string>
#include "ClockerListener.hpp"
#include "ClockerModel.hpp"
#include "ClockerXmlHook.hpp"
using namespace std;
int main(int argc, char* argv[]){
// Retrieve test path from command line first argument. Default to “” which resolve
// to the top level suite.
std::string reportPath = (argc == 2) ? std::string(argv[1]) : std::string("report/cppunit-report.xml");
// Create the event manager and test controller
CPPUNIT_NS::TestResult controller;
// Add a listener that collects test result
CPPUNIT_NS::TestResultCollector result;
controller.addListener( &result );
// Add a listener that print dots as test run.
CPPUNIT_NS::BriefTestProgressListener progress;
ClockerModel* clockerModel= new ClockerModel();
ClockerListener clocker(clockerModel,true);
controller.addListener( &progress );
controller.addListener( &clocker ) ;
ClockerXmlHook* xmlHook = new ClockerXmlHook( clockerModel );
// Add the top suite to the test runner
CPPUNIT_NS::TestRunner runner;
runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
runner.run( controller );
// Print test in a compiler compatible format.
CPPUNIT_NS::CompilerOutputter outputter( &result, CPPUNIT_NS::stdCOut() );
outputter.write();
// Uncomment this for XML output
std::ofstream file(reportPath.c_str());
CPPUNIT_NS::XmlOutputter xml( &result, file );
xml.addHook( xmlHook );
xml.write();
file.close();
return 0;
//return result.wasSuccessful() ? 0 : 1;
} |
|