runner.cpp
/*
*
* Copyright (C) 2004 Zack Rusin <zack@kde.org>
* Copyright (C) 2005 Jeroen Wijnhout <Jeroen.Wijnhout@kdemail.net>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <iostream>
using namespace std;
#include <qregexp.h>
#include <qdir.h>
#include <qmetaobject.h>
#include <kdebug.h>
#include <klibloader.h>
#include <kglobal.h>
#include <kstandarddirs.h>
#include "runner.h"
#include "tester.h"
namespace KUnitTest
{
Runner *Runner::s_self = 0L;
bool Runner::s_debugCapturingEnabled = false;
void Runner::registerTester(const char *name, Tester *test)
{
Runner::self()->m_registry.insert(name, test);
}
void Runner::loadModules(const QString &folder, const QString &query)
{
QRegExp reQuery(query);
QDir dir(folder, "kunittest_*.la");
// Add the folder to the "module" resource such that the KLibLoader can
// find the modules in this folder.
KGlobal::dirs()->addResourceDir("module", folder);
kdDebug() << "Looking in folder: " << dir.absPath() << endl;
// Get a list of all modules.
QStringList modules = dir.entryList();
for ( uint i = 0; i < modules.count(); ++i )
{
QString module = modules[i];
kdDebug() << "Module: " << dir.absPath() + "/" + module << endl;
if ( reQuery.search(module) != -1 )
{
// strip the .la extension
module.truncate(module.length()-3);
KLibFactory *factory = KLibLoader::self()->factory(module.local8Bit());
if ( factory )
factory->create();
else {
kdWarning() << "\tError loading " << module << " : " << KLibLoader::self()->lastErrorMessage() << endl;
::exit( 1 );
}
}
else
kdDebug() << "\tModule doesn't match." << endl;
}
}
void Runner::setDebugCapturingEnabled(bool enabled)
{
s_debugCapturingEnabled = enabled;
}
RegistryType &Runner::registry()
{
return m_registry;
}
int Runner::numberOfTestCases()
{
return m_registry.count();
}
Runner *Runner::self()
{
if ( s_self == 0L ) s_self = new Runner();
return s_self;
}
Runner::Runner()
{
reset();
}
int Runner::numberOfTests() const
{
return globalSteps;
}
int Runner::numberOfPassedTests() const
{
return globalPasses;
}
int Runner::numberOfFailedTests() const
{
return globalFails;
}
int Runner::numberOfExpectedFailures() const
{
return globalXFails;
}
int Runner::numberOfSkippedTests() const
{
return globalSkipped;
}
void Runner::reset()
{
globalSteps = 0;
globalPasses = 0;
globalFails = 0;
globalXFails = 0;
globalXPasses = 0;
globalSkipped = 0;
}
int Runner::runTests()
{
globalSteps = 0;
globalPasses = 0;
globalFails = 0;
globalXFails = 0;
globalXPasses = 0;
globalSkipped = 0;
cout << "# Running normal tests... #" << endl << endl;
RegistryIteratorType it(m_registry);
for( ; it.current(); ++it )
runTest(it.currentKey());
#if 0 // very thorough, but not very readable
cout << "# Done with normal tests:" << endl;
cout << " Total test cases: " << m_registry.count() << endl;
cout << " Total test steps : " << globalSteps << endl;
cout << " Total passed test steps (including unexpected) : " << globalPasses << endl;
cout << " Total unexpected passed test steps : " << globalXPasses << endl;
cout << " Total failed test steps (including expected) : " << globalFails << endl;
cout << " Total expected failed test steps : " << globalXFails << endl;
cout << " Total skipped test steps : " << globalSkipped << endl;
#else
unsigned int numTests = m_registry.count(); // should this be globalSteps instead?
QString str;
if ( globalFails == 0 )
if ( globalXFails == 0 )
str = QString( "All %1 tests passed" ).arg( numTests );
else
str = QString( "All %1 tests behaved as expected (%2 expected failures)" ).arg( numTests ).arg( globalXFails );
else
if ( globalXPasses == 0 )
str = QString( "%1 of %2 tests failed" ).arg( globalFails ).arg( numTests );
else
str = QString( "%1 of %2 tests did not behave as expected (%1 unexpected passes)" ).arg( globalFails ).arg( numTests ).arg( globalXPasses );
if ( globalSkipped )
str += QString( " (%1 tests skipped)" ).arg( globalSkipped );
cout << str.local8Bit() << endl;
#endif
return m_registry.count();
}
void Runner::runMatchingTests(const QString &prefix)
{
RegistryIteratorType it(m_registry);
for( ; it.current(); ++it )
if ( QString(it.currentKey()).startsWith(prefix) )
runTest(it.currentKey());
}
void Runner::runTest(const char *name)
{
Tester *test = m_registry.find(name);
if ( test == 0L ) return;
if ( s_debugCapturingEnabled )
{
cout << "KUnitTest_Debug_Start[" << name << "]" << endl;
}
test->results()->clear();
test->allTests();
if ( s_debugCapturingEnabled )
{
cout << "KUnitTest_Debug_End[" << name << "]" << endl << endl << flush;
}
int numPass = 0;
int numFail = 0;
int numXFail = 0;
int numXPass = 0;
int numSkip = 0;
QStringList xpassList;
QStringList errorList;
QStringList xfailList;
QStringList skipList;
if ( test->inherits("KUnitTest::SlotTester") )
{
SlotTester *sltest = static_cast<SlotTester*>(test);
TestResultsListIteratorType it(sltest->resultsList());
for ( ; it.current(); ++it)
{
numPass += it.current()->passed() + it.current()->xpasses();
numFail += it.current()->errors() + it.current()->xfails();
numXFail += it.current()->xfails();
numXPass += it.current()->xpasses();
numSkip += it.current()->skipped();
globalSteps += it.current()->testsFinished();
xpassList += it.current()->xpassList();
errorList += it.current()->errorList();
xfailList += it.current()->xfailList();
skipList += it.current()->skipList();
}
}
else
{
numPass= test->results()->passed() + test->results()->xpasses();
numFail= test->results()->errors() + test->results()->xfails();
numXFail = test->results()->xfails();
numXPass = test->results()->xpasses();
numSkip= test->results()->skipped();
globalSteps += test->results()->testsFinished();
xpassList += test->results()->xpassList();
errorList += test->results()->errorList();
xfailList += test->results()->xfailList();
skipList += test->results()->skipList();
}
globalPasses += numPass;
globalFails += numFail;
globalXFails += numXFail;
globalXPasses += numXPass;
globalSkipped += numSkip;
cout << name << " - ";
cout << numPass << " test" << ( ( 1 == numPass )?"":"s") << " passed";
if ( 0 < xpassList.count() ) {
cout << " (" << numXPass << " unexpected pass" << ( ( 1 == numXPass )?"":"es") << ")";
}
cout << ", " << numFail << " test" << ( ( 1 == numFail )?"":"s") << " failed";
if ( 0 < numXFail ) {
cout << " (" << numXFail << " expected failure" << ( ( 1 == numXFail )?"":"s") << ")";
}
if ( 0 < numSkip ) {
cout << "; also " << numSkip << " skipped";
}
cout << endl;
if ( 0 < numXPass ) {
cout << " Unexpected pass" << ( ( 1 == numXPass )?"":"es") << ":" << endl;
QStringList list = xpassList;
for ( QStringList::Iterator itr = list.begin(); itr != list.end(); ++itr ) {
cout << "\t" << (*itr).latin1() << endl;
}
}
if ( 0 < (numFail - numXFail) ) {
cout << " Unexpected failure" << ( ( 1 == numFail )?"":"s") << ":" << endl;
QStringList list = errorList;
for ( QStringList::Iterator itr = list.begin(); itr != list.end(); ++itr ) {
cout << "\t" << (*itr).latin1() << endl;
}
}
if ( 0 < numXFail ) {
cout << " Expected failure" << ( ( 1 == numXFail)?"":"s") << ":" << endl;
QStringList list = xfailList;
for ( QStringList::Iterator itr = list.begin(); itr != list.end(); ++itr ) {
cout << "\t" << (*itr).latin1() << endl;
}
}
if ( 0 < numSkip ) {
cout << " Skipped test" << ( ( 1 == numSkip )?"":"s") << ":" << endl;
QStringList list = skipList;
for ( QStringList::Iterator itr = list.begin(); itr != list.end(); ++itr ) {
cout << "\t" << (*itr).latin1() << endl;
}
}
cout << endl;
emit finished(name, test);
}
}
#include "runner.moc"
KUnitTest::TestResultsListIteratorType
QAsciiDictIterator< TestResults > TestResultsListIteratorType
Definition: tester.h:512
KUnitTest::Tester
Definition: tester.h:522
KUnitTest::TestResults::xpasses
int xpasses() const
Definition: tester.h:476
KUnitTest::TestResults::passed
int passed() const
Definition: tester.h:482
KUnitTest::TestResults::clear
virtual void clear()
Definition: tester.h:443
tester.h
runner.h
KUnitTest::TestResults::xpassList
QStringList xpassList() const
Definition: tester.h:491
KUnitTest::TestResults::testsFinished
int testsFinished() const
Definition: tester.h:467
KUnitTest::Runner
Definition: runner.h:97
KUnitTest::TestResults::skipList
QStringList skipList() const
Definition: tester.h:494
KUnitTest::TestResults::errors
int errors() const
Definition: tester.h:470
KUnitTest::SlotTester
Definition: tester.h:686
KUnitTest::RegistryType
QAsciiDict< Tester > RegistryType
Definition: runner.h:75
KUnitTest::TestResults::errorList
QStringList errorList() const
Definition: tester.h:485
KUnitTest::TestResults::xfails
int xfails() const
Definition: tester.h:473
KUnitTest::TestResults::xfailList
QStringList xfailList() const
Definition: tester.h:488
KUnitTest::Tester::results
virtual TestResults * results()
Definition: tester.h:539
KUnitTest::RegistryIteratorType
QAsciiDictIterator< Tester > RegistryIteratorType
Definition: runner.h:78
KUnitTest::Tester::allTests
virtual void allTests()=0
KUnitTest::TestResults::skipped
int skipped() const
Definition: tester.h:479

KDE Home | KDE Accessibility Home | Description of Access Keys