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