KUnitTest
runner.cpp
Go to the documentation of this file.00001
00028 #include "runner.h"
00029
00030 #include <stdio.h>
00031 #include <iostream>
00032 using namespace std;
00033
00034 #include <QtCore/QRegExp>
00035 #include <QtCore/QDir>
00036 #include <QtCore/QMetaEnum>
00037
00038 #include <kdebug.h>
00039 #include <klibloader.h>
00040 #include <kglobal.h>
00041 #include <kstandarddirs.h>
00042
00043 #include "tester.h"
00044
00045 namespace KUnitTest
00046 {
00047 Runner *Runner::s_self = 0L;
00048 bool Runner::s_debugCapturingEnabled = false;
00049
00050 void Runner::registerTester(const char *name, Tester *test)
00051 {
00052 Runner::self()->m_registry.insert(name, test);
00053 }
00054
00055 void Runner::loadModules(const QString &folder, const QString &query)
00056 {
00057 QRegExp reQuery(query);
00058 QDir dir(folder, "kunittest_*.la");
00059
00060
00061
00062 KGlobal::dirs()->addResourceDir("module", folder);
00063 kDebug() << "Looking in folder: " << dir.absolutePath();
00064
00065
00066 QStringList modules = dir.entryList();
00067
00068 for ( int i = 0; i < modules.count(); ++i )
00069 {
00070 QString module = modules[i];
00071 kDebug() << "Module: " << dir.absolutePath() + '/' + module;
00072
00073 if ( reQuery.indexIn(module) != -1 )
00074 {
00075
00076 module.truncate(module.length()-3);
00077 KPluginLoader loader(module.toLocal8Bit());
00078 KPluginFactory *factory = loader.factory();
00079 if ( factory )
00080 factory->create<QObject>();
00081 else {
00082 kWarning() << "\tError loading " << module << " : " << loader.errorString();
00083 ::exit( 1 );
00084 }
00085 }
00086 else
00087 kDebug() << "\tModule doesn't match.";
00088 }
00089 }
00090
00091 void Runner::setDebugCapturingEnabled(bool enabled)
00092 {
00093 s_debugCapturingEnabled = enabled;
00094 }
00095
00096
00097 Registry &Runner::registry()
00098 {
00099 return m_registry;
00100 }
00101
00102 int Runner::numberOfTestCases()
00103 {
00104 return m_registry.count();
00105 }
00106
00107 Runner *Runner::self()
00108 {
00109 if ( !s_self )
00110 s_self = new Runner();
00111
00112 return s_self;
00113 }
00114
00115
00116 Runner::Runner()
00117 {
00118 reset();
00119 }
00120
00121 int Runner::numberOfTests() const
00122 {
00123 return globalSteps;
00124 }
00125
00126 int Runner::numberOfPassedTests() const
00127 {
00128 return globalPasses;
00129 }
00130
00131 int Runner::numberOfFailedTests() const
00132 {
00133 return globalFails;
00134 }
00135
00136 int Runner::numberOfExpectedFailures() const
00137 {
00138 return globalXFails;
00139 }
00140
00141 int Runner::numberOfSkippedTests() const
00142 {
00143 return globalSkipped;
00144 }
00145
00146 void Runner::reset()
00147 {
00148 globalSteps = 0;
00149 globalPasses = 0;
00150 globalFails = 0;
00151 globalXFails = 0;
00152 globalXPasses = 0;
00153 globalSkipped = 0;
00154 }
00155
00156 int Runner::runTests()
00157 {
00158 globalSteps = 0;
00159 globalPasses = 0;
00160 globalFails = 0;
00161 globalXFails = 0;
00162 globalXPasses = 0;
00163 globalSkipped = 0;
00164
00165 cout << "# Running normal tests... #" << endl << endl;
00166
00167 Registry::const_iterator it = m_registry.constBegin();
00168 for( ; it != m_registry.constEnd(); ++it )
00169 runTest( it.key( ) );
00170
00171 #if 0 // very thorough, but not very readable
00172 cout << "# Done with normal tests:" << endl;
00173 cout << " Total test cases: " << m_registry.count() << endl;
00174 cout << " Total test steps : " << globalSteps << endl;
00175 cout << " Total passed test steps (including unexpected) : " << globalPasses << endl;
00176 cout << " Total unexpected passed test steps : " << globalXPasses << endl;
00177 cout << " Total failed test steps (including expected) : " << globalFails << endl;
00178 cout << " Total expected failed test steps : " << globalXFails << endl;
00179 cout << " Total skipped test steps : " << globalSkipped << endl;
00180 #else
00181 unsigned int numTests = m_registry.count();
00182 QString str;
00183 if ( globalFails == 0 )
00184 if ( globalXFails == 0 )
00185 str = QString( "All %1 tests passed" ).arg( numTests );
00186 else
00187 str = QString( "All %1 tests behaved as expected (%2 expected failures)" ).arg( numTests ).arg( globalXFails );
00188 else
00189 if ( globalXPasses == 0 )
00190 str = QString( "%1 of %2 tests failed" ).arg( globalFails ).arg( numTests );
00191 else
00192 str = QString( "%1 of %2 tests did not behave as expected (%1 unexpected passes)" ).arg( globalFails ).arg( numTests ).arg( globalXPasses );
00193 if ( globalSkipped )
00194 str += QString( " (%1 tests skipped)" ).arg( globalSkipped );
00195 cout << str.toLocal8Bit().constData() << endl;
00196 #endif
00197
00198 return m_registry.count();
00199 }
00200
00201 void Runner::runMatchingTests(const QString &prefix)
00202 {
00203 Registry::const_iterator it = m_registry.constBegin();
00204 for( ; it != m_registry.constEnd(); ++it )
00205 if ( QString( it.key() ).startsWith(prefix) )
00206 runTest( it.key() );
00207 }
00208
00209 void Runner::runTest(const char *name)
00210 {
00211 Tester *test = m_registry.value( name );
00212 if ( !test ) return;
00213
00214 if ( s_debugCapturingEnabled )
00215 {
00216 cout << "KUnitTest_Debug_Start[" << name << "]" << endl;
00217 }
00218
00219 test->results()->clear();
00220 test->allTests();
00221
00222 if ( s_debugCapturingEnabled )
00223 {
00224 cout << "KUnitTest_Debug_End[" << name << "]" << endl << endl << flush;
00225 }
00226
00227 int numPass = 0;
00228 int numFail = 0;
00229 int numXFail = 0;
00230 int numXPass = 0;
00231 int numSkip = 0;
00232
00233 if ( test->inherits("KUnitTest::SlotTester") )
00234 {
00235 SlotTester *sltest = static_cast<SlotTester*>(test);
00236 foreach( TestResults* res, sltest->resultsList() )
00237 {
00238 numPass += res->passed() + res->xpasses();
00239 numFail += res->errors() + res->xfails();
00240 numXFail += res->xfails();
00241 numXPass += res->xpasses();
00242 numSkip += res->skipped();
00243 globalSteps += res->testsFinished();
00244 }
00245 }
00246 else
00247 {
00248 numPass= test->results()->passed() + test->results()->xpasses();
00249 numFail= test->results()->errors() + test->results()->xfails();
00250 numXFail = test->results()->xfails();
00251 numXPass = test->results()->xpasses();
00252 numSkip= test->results()->skipped();
00253 globalSteps += test->results()->testsFinished();
00254 }
00255
00256
00257 globalPasses += numPass;
00258 globalFails += numFail;
00259 globalXFails += numXFail;
00260 globalXPasses += numXPass;
00261 globalSkipped += numSkip;
00262
00263 cout << name << " - ";
00264 cout << numPass << " test" << ( ( 1 == numPass )?"":"s") << " passed";
00265 if ( 0 < test->results()->xpassList().count() ) {
00266 cout << " (" << numXPass << " unexpected pass" << ( ( 1 == numXPass )?"":"es") << ")";
00267 }
00268 cout << ", " << numFail << " test" << ( ( 1 == numFail )?"":"s") << " failed";
00269 if ( 0 < numXFail ) {
00270 cout << " (" << numXFail << " expected failure" << ( ( 1 == numXFail )?"":"s") << ")";
00271 }
00272 if ( 0 < numSkip ) {
00273 cout << "; also " << numSkip << " skipped";
00274 }
00275 cout << endl;
00276
00277 if ( 0 < numXPass ) {
00278 cout << " Unexpected pass" << ( ( 1 == numXPass )?"":"es") << ":" << endl;
00279 QStringList list = test->results()->xpassList();
00280 for ( QStringList::Iterator itr = list.begin(); itr != list.end(); ++itr ) {
00281 cout << "\t" << (*itr).toLatin1().constData() << endl;
00282 }
00283 }
00284 if ( 0 < (numFail - numXFail) ) {
00285 cout << " Unexpected failure" << ( ( 1 == numFail )?"":"s") << ":" << endl;
00286 QStringList list = test->results()->errorList();
00287 for ( QStringList::Iterator itr = list.begin(); itr != list.end(); ++itr ) {
00288 cout << "\t" << (*itr).toLatin1().constData() << endl;
00289 }
00290 }
00291 if ( 0 < numXFail ) {
00292 cout << " Expected failure" << ( ( 1 == numXFail)?"":"s") << ":" << endl;
00293 QStringList list = test->results()->xfailList();
00294 for ( QStringList::Iterator itr = list.begin(); itr != list.end(); ++itr ) {
00295 cout << "\t" << (*itr).toLatin1().constData() << endl;
00296 }
00297 }
00298 if ( 0 < numSkip ) {
00299 cout << " Skipped test" << ( ( 1 == numSkip )?"":"s") << ":" << endl;
00300 QStringList list = test->results()->skipList();
00301 for ( QStringList::Iterator itr = list.begin(); itr != list.end(); ++itr ) {
00302 cout << "\t" << (*itr).toLatin1().constData() << endl;
00303 }
00304 }
00305 cout << endl;
00306
00307 emit finished(name, test);
00308 }
00309 }
00310
00311 #include "runner.moc"
00312