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