summaryrefslogtreecommitdiff
path: root/src/cppunit
diff options
context:
space:
mode:
Diffstat (limited to 'src/cppunit')
-rw-r--r--src/cppunit/Makefile.am8
-rw-r--r--src/cppunit/RepeatedTest.cpp9
-rw-r--r--src/cppunit/Test.cpp93
-rw-r--r--src/cppunit/TestCase.cpp118
-rw-r--r--src/cppunit/TestComposite.cpp53
-rw-r--r--src/cppunit/TestFailure.cpp8
-rw-r--r--src/cppunit/TestLeaf.cpp28
-rw-r--r--src/cppunit/TestPath.cpp236
-rw-r--r--src/cppunit/TestRunner.cpp180
-rw-r--r--src/cppunit/TestSuite.cpp70
-rw-r--r--src/cppunit/TextTestRunner.cpp181
-rw-r--r--src/cppunit/XmlOutputter.cpp26
-rw-r--r--src/cppunit/cppunit.dsp44
-rw-r--r--src/cppunit/cppunit_dll.dsp32
14 files changed, 797 insertions, 289 deletions
diff --git a/src/cppunit/Makefile.am b/src/cppunit/Makefile.am
index 8b239de..3675c00 100644
--- a/src/cppunit/Makefile.am
+++ b/src/cppunit/Makefile.am
@@ -1,5 +1,5 @@
#
-# $Id: Makefile.am,v 1.19 2002-03-28 15:47:08 blep Exp $
+# $Id: Makefile.am,v 1.20 2002-04-12 19:28:47 blep Exp $
#
EXTRA_DIST = cppunit.dsw cppunit.dsp cppunit_dll.dsp DllMain.cpp
@@ -15,19 +15,25 @@ libcppunit_la_SOURCES = \
RepeatedTest.cpp \
SourceLine.cpp \
SynchronizedObject.cpp \
+ Test.cpp \
TestAssert.cpp \
TestCase.cpp \
+ TestComposite.cpp \
TestFactoryRegistry.cpp \
TestFailure.cpp \
+ TestLeaf.cpp \
+ TestPath.cpp \
TestResult.cpp \
TestResultCollector.cpp \
TestRunner.cpp \
TestSetUp.cpp \
TestSucessListener.cpp \
TestSuite.cpp \
+ TestTest.cpp \
TextOutputter.cpp \
TextTestProgressListener.cpp \
TextTestResult.cpp \
+ TextTestRunner.cpp \
TypeInfoHelper.cpp \
XmlOutputter.cpp
diff --git a/src/cppunit/RepeatedTest.cpp b/src/cppunit/RepeatedTest.cpp
index bfe1f72..58b1805 100644
--- a/src/cppunit/RepeatedTest.cpp
+++ b/src/cppunit/RepeatedTest.cpp
@@ -9,17 +9,10 @@ namespace CppUnit {
int
RepeatedTest::countTestCases() const
{
- return TestDecorator::countTestCases () * m_timesRepeat;
+ return TestDecorator::countTestCases() * m_timesRepeat;
}
-// Returns the name of the test instance.
-std::string
-RepeatedTest::toString() const
-{
- return TestDecorator::toString () + " (repeated)";
-}
-
// Runs a repeated test
void
RepeatedTest::run( TestResult *result )
diff --git a/src/cppunit/Test.cpp b/src/cppunit/Test.cpp
new file mode 100644
index 0000000..b751bad
--- /dev/null
+++ b/src/cppunit/Test.cpp
@@ -0,0 +1,93 @@
+#include <cppunit/Portability.h>
+#include <cppunit/Test.h>
+#include <cppunit/TestPath.h>
+#include <stdexcept>
+
+
+namespace CppUnit {
+
+Test *
+Test::getChildTestAt( int index ) const
+{
+ checkIsValidIndex( index );
+ return doGetChildTestAt( index );
+}
+
+
+Test *
+Test::findTest( const std::string &testName ) const
+{
+ TestPath path;
+ // since path is discarded, it is really a const method.
+ const_cast<Test *>(this)->findTestPath( testName, path );
+ if ( !path.isValid() )
+ throw std::invalid_argument( "No test named <" + testName + "> found in test <"
+ + getName() + ">." );
+ return path.getChildTest();
+}
+
+
+bool
+Test::findTestPath( const std::string &testName,
+ TestPath &testPath )
+{
+ if ( getName() == testName )
+ {
+ testPath.add( this );
+ return true;
+ }
+
+ int childCount = getChildTestCount();
+ for ( int childIndex =0; childIndex < childCount; ++childIndex )
+ {
+ if ( getChildTestAt( childIndex )->findTestPath( testName, testPath ) )
+ {
+ testPath.insert( this, 0 );
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+bool
+Test::findTestPath( const Test *test,
+ TestPath &testPath )
+{
+ if ( this == test )
+ {
+ testPath.add( this );
+ return true;
+ }
+
+ int childCount = getChildTestCount();
+ for ( int childIndex =0; childIndex < childCount; ++childIndex )
+ {
+ if ( getChildTestAt( childIndex )->findTestPath( test, testPath ) )
+ {
+ testPath.insert( this, 0 );
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+TestPath
+Test::resolveTestPath( const std::string &testPath )
+{
+ return TestPath( this, testPath );
+}
+
+
+void
+Test::checkIsValidIndex( int index ) const
+{
+ if ( index < 0 || index >= getChildTestCount() )
+ throw std::out_of_range( "Test::checkValidIndex(): invalid index" );
+}
+
+
+} // namespace CppUnit
diff --git a/src/cppunit/TestCase.cpp b/src/cppunit/TestCase.cpp
index b2edb90..4fb388a 100644
--- a/src/cppunit/TestCase.cpp
+++ b/src/cppunit/TestCase.cpp
@@ -2,19 +2,21 @@
#include <typeinfo>
#include <stdexcept>
-#include "cppunit/TestCase.h"
-#include "cppunit/Exception.h"
-#include "cppunit/TestResult.h"
+#include <cppunit/TestCase.h>
+#include <cppunit/Exception.h>
+#include <cppunit/TestResult.h>
namespace CppUnit {
-/// Create a default TestResult
-CppUnit::TestResult*
-TestCase::defaultResult()
-{
- return new TestResult;
-}
+
+/** Constructs a test case.
+ * \param name the name of the TestCase.
+ **/
+TestCase::TestCase( const std::string &name )
+ : m_name(name)
+{
+}
/// Run the test and catch any exceptions that are triggered by it
@@ -24,49 +26,38 @@ TestCase::run( TestResult *result )
result->startTest(this);
try {
- setUp();
-
- try {
- runTest();
- }
- catch ( Exception &e ) {
- Exception *copy = e.clone();
- result->addFailure( this, copy );
- }
- catch ( std::exception &e ) {
- result->addError( this, new Exception( e.what() ) );
- }
- catch (...) {
- Exception *e = new Exception( "caught unknown exception" );
- result->addError( this, e );
- }
-
- try {
- tearDown();
- }
- catch (...) {
- result->addError( this, new Exception( "tearDown() failed" ) );
- }
+ setUp();
+
+ try {
+ runTest();
+ }
+ catch ( Exception &e ) {
+ Exception *copy = e.clone();
+ result->addFailure( this, copy );
+ }
+ catch ( std::exception &e ) {
+ result->addError( this, new Exception( e.what() ) );
+ }
+ catch (...) {
+ Exception *e = new Exception( "caught unknown exception" );
+ result->addError( this, e );
+ }
+
+ try {
+ tearDown();
+ }
+ catch (...) {
+ result->addError( this, new Exception( "tearDown() failed" ) );
+ }
}
catch (...) {
- result->addError( this, new Exception( "setUp() failed" ) );
+ result->addError( this, new Exception( "setUp() failed" ) );
}
result->endTest( this );
}
-/// A default run method
-TestResult *
-TestCase::run()
-{
- TestResult *result = defaultResult();
-
- run (result);
- return result;
-}
-
-
/// All the work for runTest is deferred to subclasses
void
TestCase::runTest()
@@ -74,17 +65,11 @@ TestCase::runTest()
}
-/** Constructs a test case.
- * \param name the name of the TestCase.
- **/
-TestCase::TestCase( std::string name )
- : m_name(name)
-{
-}
-
-
/** Constructs a test case for a suite.
- * This TestCase is intended for use by the TestCaller and should not
+ * \deprecated This constructor was used by fixture when TestFixture did not exist.
+ * Have your fixture inherits TestFixture instead of TestCase.
+ * \internal
+ * This TestCase was intended for use by the TestCaller and should not
* be used by a test case for which run() is called.
**/
TestCase::TestCase()
@@ -99,37 +84,12 @@ TestCase::~TestCase()
}
-/// Returns a count of all the tests executed
-int
-TestCase::countTestCases() const
-{
- return 1;
-}
-
-
/// Returns the name of the test case
std::string
TestCase::getName() const
{
return m_name;
}
-
-
-/// Returns the name of the test case instance
-std::string
-TestCase::toString() const
-{
- std::string className;
-
-#if CPPUNIT_USE_TYPEINFO_NAME
- const std::type_info& thisClass = typeid( *this );
- className = thisClass.name();
-#else
- className = "TestCase";
-#endif
-
- return className + "." + getName();
-}
} // namespace CppUnit
diff --git a/src/cppunit/TestComposite.cpp b/src/cppunit/TestComposite.cpp
new file mode 100644
index 0000000..e5f38c3
--- /dev/null
+++ b/src/cppunit/TestComposite.cpp
@@ -0,0 +1,53 @@
+#include <cppunit/TestComposite.h>
+#include <cppunit/TestResult.h>
+
+
+namespace CppUnit {
+
+TestComposite::TestComposite( const std::string &name )
+ : m_name( name )
+{
+}
+
+
+TestComposite::~TestComposite()
+{
+}
+
+
+void
+TestComposite::run( TestResult *result )
+{
+ int childCount = getChildTestCount();
+ for ( int index =0; index < childCount; ++index )
+ {
+ if ( result->shouldStop() )
+ break;
+
+ getChildTestAt( index )->run( result );
+ }
+}
+
+
+int
+TestComposite::countTestCases() const
+{
+ int count = 0;
+
+ int childCount = getChildTestCount();
+ for ( int index =0; index < childCount; ++index )
+ count += getChildTestAt( index )->countTestCases();
+
+ return count;
+}
+
+
+std::string
+TestComposite::getName() const
+{
+ return m_name;
+}
+
+
+} // namespace CppUnit
+
diff --git a/src/cppunit/TestFailure.cpp b/src/cppunit/TestFailure.cpp
index 8404427..474761d 100644
--- a/src/cppunit/TestFailure.cpp
+++ b/src/cppunit/TestFailure.cpp
@@ -60,14 +60,6 @@ TestFailure::failedTestName() const
}
-/// Returns a short description of the failure.
-std::string
-TestFailure::toString() const
-{
- return m_failedTest->toString() + ": " + m_thrownException->what();
-}
-
-
TestFailure *
TestFailure::clone() const
{
diff --git a/src/cppunit/TestLeaf.cpp b/src/cppunit/TestLeaf.cpp
new file mode 100644
index 0000000..80160cb
--- /dev/null
+++ b/src/cppunit/TestLeaf.cpp
@@ -0,0 +1,28 @@
+#include <cppunit/TestLeaf.h>
+
+
+namespace CppUnit {
+
+
+int
+TestLeaf::countTestCases() const
+{
+ return 1;
+}
+
+
+int
+TestLeaf::getChildTestCount() const
+{
+ return 0;
+}
+
+
+Test *
+TestLeaf::doGetChildTestAt( int index ) const
+{
+ checkIsValidIndex( index );
+ return NULL; // never called, checkIsValidIndex() always throw.
+}
+
+} // namespace CppUnit
diff --git a/src/cppunit/TestPath.cpp b/src/cppunit/TestPath.cpp
new file mode 100644
index 0000000..ecb89fd
--- /dev/null
+++ b/src/cppunit/TestPath.cpp
@@ -0,0 +1,236 @@
+#include <cppunit/Portability.h>
+#include <cppunit/Test.h>
+#include <cppunit/TestPath.h>
+#include <stdexcept>
+
+
+namespace CppUnit {
+
+
+TestPath::TestPath()
+{
+}
+
+
+TestPath::TestPath( Test *root )
+{
+ add( root );
+}
+
+
+TestPath::TestPath( const TestPath &other,
+ int indexFirst,
+ int count )
+{
+ int countAdjustment = 0;
+ if ( indexFirst < 0 )
+ {
+ countAdjustment = indexFirst;
+ indexFirst = 0;
+ }
+
+ if ( count < 0 )
+ count = other.getTestCount();
+ else
+ count += countAdjustment;
+
+ int index = indexFirst;
+ while ( count-- > 0 && index < other.getTestCount() )
+ add( other.getTestAt( index++ ) );
+}
+
+
+TestPath::TestPath( Test *searchRoot,
+ const std::string &pathAsString )
+{
+ PathTestNames testNames;
+
+ Test *parentTest = findActualRoot( searchRoot, pathAsString, testNames );
+ add( parentTest );
+
+ for ( int index = 1; index < testNames.size(); ++index )
+ {
+ bool childFound = false;
+ for ( int childIndex =0; childIndex < parentTest->getChildTestCount(); ++childIndex )
+ {
+ if ( parentTest->getChildTestAt( childIndex )->getName() == testNames[index] )
+ {
+ childFound = true;
+ parentTest = parentTest->getChildTestAt( childIndex );
+ break;
+ }
+ }
+
+ if ( !childFound )
+ throw std::invalid_argument( "TestPath::TestPath(): failed to resolve test name <"+
+ testNames[index] + "> of path <" + pathAsString + ">" );
+
+ add( parentTest );
+ }
+}
+
+
+TestPath::~TestPath()
+{
+}
+
+
+bool
+TestPath::isValid() const
+{
+ return getTestCount() > 0;
+}
+
+
+void
+TestPath::add( Test *test )
+{
+ _tests.push_back( test );
+}
+
+
+void
+TestPath::add( const TestPath &path )
+{
+ for ( int index =0; index < path.getTestCount(); ++index )
+ add( path.getTestAt( index ) );
+}
+
+
+void
+TestPath::insert( Test *test,
+ int index )
+{
+ if ( index < 0 || index > getTestCount() )
+ throw std::out_of_range( "TestPath::insert(): index out of range" );
+ _tests.insert( _tests.begin() + index, test );
+}
+
+void
+TestPath::insert( const TestPath &path,
+ int index )
+{
+ int itemIndex = path.getTestCount() -1;
+ while ( itemIndex >= 0 )
+ insert( path.getTestAt( itemIndex-- ), index );
+}
+
+
+void
+TestPath::removeTests()
+{
+ while ( isValid() )
+ removeTest( 0 );
+}
+
+
+void
+TestPath::removeTest( int index )
+{
+ checkIndexValid( index );
+ _tests.erase( _tests.begin() + index );
+}
+
+
+void
+TestPath::up()
+{
+ checkIndexValid( 0 );
+ removeTest( getTestCount() -1 );
+}
+
+
+int
+TestPath::getTestCount() const
+{
+ return _tests.size();
+}
+
+
+Test *
+TestPath::getTestAt( int index ) const
+{
+ checkIndexValid( index );
+ return _tests[index];
+}
+
+
+Test *
+TestPath::getChildTest() const
+{
+ return getTestAt( getTestCount() -1 );
+}
+
+
+void
+TestPath::checkIndexValid( int index ) const
+{
+ if ( index < 0 || index >= getTestCount() )
+ throw std::out_of_range( "TestPath::checkIndexValid(): index out of range" );
+}
+
+
+std::string
+TestPath::toString() const
+{
+ std::string asString( "/" );
+ for ( int index =0; index < getTestCount(); ++index )
+ {
+ if ( index > 0 )
+ asString += '/';
+ asString += getTestAt(index)->getName();
+ }
+
+ return asString;
+}
+
+
+Test *
+TestPath::findActualRoot( Test *searchRoot,
+ const std::string &pathAsString,
+ PathTestNames &testNames )
+{
+ bool isRelative = splitPathString( pathAsString, testNames );
+
+ if ( isRelative && pathAsString.empty() )
+ return searchRoot;
+
+ if ( testNames.empty() )
+ throw std::invalid_argument( "TestPath::TestPath(): invalid root or root name in absolute path" );
+
+ Test *root = isRelative ? searchRoot->findTest( testNames[0] ) // throw if bad test name
+ : searchRoot;
+ if ( root->getName() != testNames[0] )
+ throw std::invalid_argument( "TestPath::TestPath(): searchRoot does not match path root name" );
+
+ return root;
+}
+
+
+bool
+TestPath::splitPathString( const std::string &pathAsString,
+ PathTestNames &testNames )
+{
+ bool isRelative = (pathAsString.substr(0,1) != "/");
+
+ int index = (isRelative ? 0 : 1);
+ while ( true )
+ {
+ int separatorIndex = pathAsString.find( '/', index );
+ if ( separatorIndex >= 0 )
+ {
+ testNames.push_back( pathAsString.substr( index, separatorIndex - index ) );
+ index = separatorIndex + 1;
+ }
+ else
+ {
+ testNames.push_back( pathAsString.substr( index ) );
+ break;
+ }
+ }
+
+ return isRelative;
+}
+
+
+} // namespace CppUnit
diff --git a/src/cppunit/TestRunner.cpp b/src/cppunit/TestRunner.cpp
index 44c11d9..9bce34d 100644
--- a/src/cppunit/TestRunner.cpp
+++ b/src/cppunit/TestRunner.cpp
@@ -1,179 +1,99 @@
-#include <cppunit/TestSuite.h>
-#include <cppunit/TextTestResult.h>
-#include <cppunit/TextOutputter.h>
-#include <cppunit/TextTestProgressListener.h>
-#include <cppunit/TestResult.h>
-#include <cppunit/ui/text/TestRunner.h>
-#include <iostream>
-
-
-namespace CppUnit {
-namespace TextUi {
-
-/*! Constructs a new text runner.
- * \param outputter used to print text result. Owned by the runner.
- */
-TestRunner::TestRunner( Outputter *outputter )
- : m_outputter( outputter )
- , m_suite( new TestSuite( "All Tests" ) )
- , m_result( new TestResultCollector() )
- , m_eventManager( new TestResult() )
-{
- if ( !m_outputter )
- m_outputter = new TextOutputter( m_result, std::cout );
- m_eventManager->addListener( m_result );
-}
+#include <cppunit/TestRunner.h>
+#include <cppunit/TestPath.h>
-TestRunner::~TestRunner()
+namespace CppUnit
{
- delete m_eventManager;
- delete m_outputter;
- delete m_result;
- delete m_suite;
-}
-
-/*! Adds the specified test.
- *
- * \param test Test to add.
- */
-void
-TestRunner::addTest( Test *test )
+TestRunner::WrappingSuite::WrappingSuite( const std::string &name )
+ : TestSuite( name )
{
- if ( test != NULL )
- m_suite->addTest( test );
}
-/*! Runs the named test case.
- *
- * \param testName Name of the test case to run. If an empty is given, then
- * all added test are run. The name must be the name of
- * of an added test.
- * \param doWait if \c true then the user must press the RETURN key
- * before the run() method exit.
- * \param doPrintResult if \c true (default) then the test result are printed
- * on the standard output.
- * \param doPrintProgress if \c true (default) then TextTestProgressListener is
- * used to show the progress.
- * \return \c true is the test was successful, \c false if the test
- * failed or was not found.
- */
-bool
-TestRunner::run( std::string testName,
- bool doWait,
- bool doPrintResult,
- bool doPrintProgress )
+int
+TestRunner::WrappingSuite::getChildTestCount() const
{
- runTestByName( testName, doPrintProgress );
- printResult( doPrintResult );
- wait( doWait );
- return m_result->wasSuccessful();
+ if ( hasOnlyOneTest() )
+ return getUniqueChildTest()->getChildTestCount();
+ return TestSuite::getChildTestCount();
}
-bool
-TestRunner::runTestByName( std::string testName,
- bool doPrintProgress )
+std::string
+TestRunner::WrappingSuite::getName() const
{
- if ( testName.empty() )
- return runTest( m_suite, doPrintProgress );
+ if ( hasOnlyOneTest() )
+ return getUniqueChildTest()->getName();
+ return TestSuite::getName();
+}
- Test *test = findTestByName( testName );
- if ( test != NULL )
- return runTest( test, doPrintProgress );
- std::cout << "Test " << testName << " not found." << std::endl;
- return false;
+Test *
+TestRunner::WrappingSuite::doGetChildTestAt( int index ) const
+{
+ if ( hasOnlyOneTest() )
+ return getUniqueChildTest()->getChildTestAt( index );
+ return TestSuite::doGetChildTestAt( index );
}
void
-TestRunner::wait( bool doWait )
+TestRunner::WrappingSuite::run( TestResult *result )
{
- if ( doWait )
- {
- std::cout << "<RETURN> to continue" << std::endl;
- std::cin.get ();
- }
+ if ( hasOnlyOneTest() )
+ getUniqueChildTest()->run( result );
+ else
+ TestSuite::run( result );
}
-void
-TestRunner::printResult( bool doPrintResult )
+bool
+TestRunner::WrappingSuite::hasOnlyOneTest() const
{
- std::cout << std::endl;
- if ( doPrintResult )
- m_outputter->write();
+ return TestSuite::getChildTestCount() == 1;
}
-Test *
-TestRunner::findTestByName( std::string name ) const
+Test *
+TestRunner::WrappingSuite::getUniqueChildTest() const
{
- for ( std::vector<Test *>::const_iterator it = m_suite->getTests().begin();
- it != m_suite->getTests().end();
- ++it )
- {
- Test *test = *it;
- if ( test->getName() == name )
- return test;
- }
- return NULL;
+ return TestSuite::doGetChildTestAt( 0 );
}
-bool
-TestRunner::runTest( Test *test,
- bool doPrintProgress )
-{
- TextTestProgressListener progress;
- if ( doPrintProgress )
- m_eventManager->addListener( &progress );
- test->run( m_eventManager );
- if ( doPrintProgress )
- m_eventManager->removeListener( &progress );
- return m_result->wasSuccessful();
+
+TestRunner::TestRunner()
+ : m_suite( new WrappingSuite() )
+{
}
-/*! Returns the result of the test run.
- * Use this after calling run() to access the result of the test run.
- */
-TestResultCollector &
-TestRunner::result() const
+TestRunner::~TestRunner()
{
- return *m_result;
+ delete m_suite;
}
-/*! Returns the event manager.
- * The instance of TestResult results returned is the one that is used to run the
- * test. Use this to register additional TestListener before running the tests.
- */
-TestResult &
-TestRunner::eventManager() const
+void
+TestRunner::addTest( Test *test )
{
- return *m_eventManager;
+ m_suite->addTest( test );
}
-/*! Specifies an alternate outputter.
- *
- * Notes that the outputter will be use after the test run only if \a printResult was
- * \c true.
- * \see CompilerOutputter, XmlOutputter, TextOutputter.
- */
void
-TestRunner::setOutputter( Outputter *outputter )
+TestRunner::run( TestResult &controller,
+ const std::string &testPath )
{
- delete m_outputter;
- m_outputter = outputter;
+ TestPath path = m_suite->resolveTestPath( testPath );
+ Test *testToRun = path.getChildTest();
+
+ testToRun->run( &controller );
}
-} // namespace TextUi
-} // namespace CppUnit
+} // namespace CppUnit
+
diff --git a/src/cppunit/TestSuite.cpp b/src/cppunit/TestSuite.cpp
index 7659939..ff9c88b 100644
--- a/src/cppunit/TestSuite.cpp
+++ b/src/cppunit/TestSuite.cpp
@@ -1,11 +1,11 @@
-#include "cppunit/TestSuite.h"
-#include "cppunit/TestResult.h"
+#include <cppunit/TestSuite.h>
+#include <cppunit/TestResult.h>
namespace CppUnit {
/// Default constructor
TestSuite::TestSuite( std::string name )
- : m_name( name )
+ : TestComposite( name )
{
}
@@ -21,43 +21,11 @@ TestSuite::~TestSuite()
void
TestSuite::deleteContents()
{
- for ( std::vector<Test *>::iterator it = m_tests.begin();
- it != m_tests.end();
- ++it)
- delete *it;
- m_tests.clear();
-}
-
-
-/// Runs the tests and collects their result in a TestResult.
-void
-TestSuite::run( TestResult *result )
-{
- for ( std::vector<Test *>::iterator it = m_tests.begin();
- it != m_tests.end();
- ++it )
- {
- if ( result->shouldStop() )
- break;
-
- Test *test = *it;
- test->run( result );
- }
-}
-
-
-/// Counts the number of test cases that will be run by this test.
-int
-TestSuite::countTestCases() const
-{
- int count = 0;
-
- for ( std::vector<Test *>::const_iterator it = m_tests.begin();
- it != m_tests.end();
- ++it )
- count += (*it)->countTestCases();
+ int childCount = getChildTestCount();
+ for ( int index =0; index < childCount; ++index )
+ delete getChildTestAt( index );
- return count;
+ m_tests.clear();
}
@@ -69,26 +37,24 @@ TestSuite::addTest( Test *test )
}
-/// Returns a string representation of the test suite.
-std::string
-TestSuite::toString() const
-{
- return "suite " + getName();
+const std::vector<Test *> &
+TestSuite::getTests() const
+{
+ return m_tests;
}
-/// Returns the name of the test suite.
-std::string
-TestSuite::getName() const
-{
- return m_name;
+int
+TestSuite::getChildTestCount() const
+{
+ return m_tests.size();
}
-const std::vector<Test *> &
-TestSuite::getTests() const
+Test *
+TestSuite::doGetChildTestAt( int index ) const
{
- return m_tests;
+ return m_tests[index];
}
diff --git a/src/cppunit/TextTestRunner.cpp b/src/cppunit/TextTestRunner.cpp
new file mode 100644
index 0000000..d190ebe
--- /dev/null
+++ b/src/cppunit/TextTestRunner.cpp
@@ -0,0 +1,181 @@
+// ==> Implementation of cppunit/ui/text/TestRunner.h
+
+#include <cppunit/TestSuite.h>
+#include <cppunit/TextTestResult.h>
+#include <cppunit/TextOutputter.h>
+#include <cppunit/TextTestProgressListener.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <iostream>
+
+
+namespace CppUnit {
+namespace TextUi {
+
+/*! Constructs a new text runner.
+ * \param outputter used to print text result. Owned by the runner.
+ */
+TestRunner::TestRunner( Outputter *outputter )
+ : m_outputter( outputter )
+ , m_suite( new TestSuite( "All Tests" ) )
+ , m_result( new TestResultCollector() )
+ , m_eventManager( new TestResult() )
+{
+ if ( !m_outputter )
+ m_outputter = new TextOutputter( m_result, std::cout );
+ m_eventManager->addListener( m_result );
+}
+
+
+TestRunner::~TestRunner()
+{
+ delete m_eventManager;
+ delete m_outputter;
+ delete m_result;
+ delete m_suite;
+}
+
+
+/*! Adds the specified test.
+ *
+ * \param test Test to add.
+ */
+void
+TestRunner::addTest( Test *test )
+{
+ if ( test != NULL )
+ m_suite->addTest( test );
+}
+
+
+/*! Runs the named test case.
+ *
+ * \param testName Name of the test case to run. If an empty is given, then
+ * all added test are run. The name must be the name of
+ * of an added test.
+ * \param doWait if \c true then the user must press the RETURN key
+ * before the run() method exit.
+ * \param doPrintResult if \c true (default) then the test result are printed
+ * on the standard output.
+ * \param doPrintProgress if \c true (default) then TextTestProgressListener is
+ * used to show the progress.
+ * \return \c true is the test was successful, \c false if the test
+ * failed or was not found.
+ */
+bool
+TestRunner::run( std::string testName,
+ bool doWait,
+ bool doPrintResult,
+ bool doPrintProgress )
+{
+ runTestByName( testName, doPrintProgress );
+ printResult( doPrintResult );
+ wait( doWait );
+ return m_result->wasSuccessful();
+}
+
+
+bool
+TestRunner::runTestByName( std::string testName,
+ bool doPrintProgress )
+{
+ if ( testName.empty() )
+ return runTest( m_suite, doPrintProgress );
+
+ Test *test = findTestByName( testName );
+ if ( test != NULL )
+ return runTest( test, doPrintProgress );
+
+ std::cout << "Test " << testName << " not found." << std::endl;
+ return false;
+}
+
+
+void
+TestRunner::wait( bool doWait )
+{
+ if ( doWait )
+ {
+ std::cout << "<RETURN> to continue" << std::endl;
+ std::cin.get ();
+ }
+}
+
+
+void
+TestRunner::printResult( bool doPrintResult )
+{
+ std::cout << std::endl;
+ if ( doPrintResult )
+ m_outputter->write();
+}
+
+
+Test *
+TestRunner::findTestByName( std::string name ) const
+{
+ for ( std::vector<Test *>::const_iterator it = m_suite->getTests().begin();
+ it != m_suite->getTests().end();
+ ++it )
+ {
+ Test *test = *it;
+ if ( test->getName() == name )
+ return test;
+ }
+ return NULL;
+}
+
+
+bool
+TestRunner::runTest( Test *test,
+ bool doPrintProgress )
+{
+ TextTestProgressListener progress;
+ if ( doPrintProgress )
+ m_eventManager->addListener( &progress );
+
+ test->run( m_eventManager );
+
+ if ( doPrintProgress )
+ m_eventManager->removeListener( &progress );
+ return m_result->wasSuccessful();
+}
+
+
+/*! Returns the result of the test run.
+ * Use this after calling run() to access the result of the test run.
+ */
+TestResultCollector &
+TestRunner::result() const
+{
+ return *m_result;
+}
+
+
+/*! Returns the event manager.
+ * The instance of TestResult results returned is the one that is used to run the
+ * test. Use this to register additional TestListener before running the tests.
+ */
+TestResult &
+TestRunner::eventManager() const
+{
+ return *m_eventManager;
+}
+
+
+/*! Specifies an alternate outputter.
+ *
+ * Notes that the outputter will be use after the test run only if \a printResult was
+ * \c true.
+ * \see CompilerOutputter, XmlOutputter, TextOutputter.
+ */
+void
+TestRunner::setOutputter( Outputter *outputter )
+{
+ delete m_outputter;
+ m_outputter = outputter;
+}
+
+
+} // namespace TextUi
+} // namespace CppUnit
diff --git a/src/cppunit/XmlOutputter.cpp b/src/cppunit/XmlOutputter.cpp
index 52ed281..7b9b2b7 100644
--- a/src/cppunit/XmlOutputter.cpp
+++ b/src/cppunit/XmlOutputter.cpp
@@ -77,7 +77,7 @@ XmlOutputter::Node::toString() const
element += node->toString();
}
- element += m_content;
+ element += escape( m_content );
element += "</";
element += m_name;
@@ -175,11 +175,25 @@ XmlOutputter::write()
void
+XmlOutputter::setStyleSheet( const std::string &styleSheet )
+{
+ m_styleSheet = styleSheet;
+}
+
+
+void
XmlOutputter::writeProlog()
{
m_stream << "<?xml version=\"1.0\" "
"encoding='" << m_encoding << "' standalone='yes' ?>"
<< std::endl;
+
+ if ( !m_styleSheet.empty() )
+ {
+ m_stream << "<?xml-stylesheet type=\"text/xsl\" href=\""
+ << m_styleSheet << "\"?>"
+ << std::endl;
+ }
}
@@ -270,13 +284,13 @@ XmlOutputter::addStatistics( Node *rootNode )
void
XmlOutputter::addFailedTest( Test *test,
- TestFailure *failure,
- int testNumber,
- Node *testsNode )
+ TestFailure *failure,
+ int testNumber,
+ Node *testsNode )
{
Exception *thrownException = failure->thrownException();
- Node *testNode = new Node( "FailedTest", thrownException->what() );
+ Node *testNode = new Node( "FailedTest" );
testsNode->addNode( testNode );
testNode->addAttribute( "id", testNumber );
testNode->addNode( new Node( "Name", test->getName() ) );
@@ -285,6 +299,8 @@ XmlOutputter::addFailedTest( Test *test,
if ( failure->sourceLine().isValid() )
addFailureLocation( failure, testNode );
+
+ testNode->addNode( new Node( "Message", thrownException->what() ) );
}
diff --git a/src/cppunit/cppunit.dsp b/src/cppunit/cppunit.dsp
index f0e9612..3764129 100644
--- a/src/cppunit/cppunit.dsp
+++ b/src/cppunit/cppunit.dsp
@@ -222,6 +222,10 @@ SOURCE=..\..\include\cppunit\SynchronizedObject.h
# End Source File
# Begin Source File
+SOURCE=.\Test.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\cppunit\Test.h
# End Source File
# Begin Source File
@@ -242,6 +246,14 @@ SOURCE=..\..\include\cppunit\TestCase.h
# End Source File
# Begin Source File
+SOURCE=.\TestComposite.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\cppunit\TestComposite.h
+# End Source File
+# Begin Source File
+
SOURCE=.\TestFailure.cpp
# End Source File
# Begin Source File
@@ -254,10 +266,26 @@ SOURCE=..\..\include\cppunit\TestFixture.h
# End Source File
# Begin Source File
+SOURCE=.\TestLeaf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\cppunit\TestLeaf.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\cppunit\TestListener.h
# End Source File
# Begin Source File
+SOURCE=.\TestPath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\cppunit\TestPath.h
+# End Source File
+# Begin Source File
+
SOURCE=.\TestResult.cpp
# End Source File
# Begin Source File
@@ -266,6 +294,14 @@ SOURCE=..\..\include\cppunit\TestResult.h
# End Source File
# Begin Source File
+SOURCE=.\TestRunner.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\cppunit\TestRunner.h
+# End Source File
+# Begin Source File
+
SOURCE=.\TestSuite.cpp
# End Source File
# Begin Source File
@@ -331,11 +367,11 @@ SOURCE=..\..\include\cppunit\Portability.h
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\TestRunner.cpp
+SOURCE=..\..\include\cppunit\ui\text\TestRunner.h
# End Source File
# Begin Source File
-SOURCE=..\..\include\cppunitui\text\TestRunner.h
+SOURCE=.\TextTestRunner.cpp
# End Source File
# Begin Source File
@@ -393,6 +429,10 @@ SOURCE=..\..\NEWS
SOURCE=..\..\doc\other_documentation.dox
# End Source File
+# Begin Source File
+
+SOURCE=..\..\TODO
+# End Source File
# End Group
# Begin Source File
diff --git a/src/cppunit/cppunit_dll.dsp b/src/cppunit/cppunit_dll.dsp
index 4e4f8d1..17d9708 100644
--- a/src/cppunit/cppunit_dll.dsp
+++ b/src/cppunit/cppunit_dll.dsp
@@ -206,6 +206,10 @@ SOURCE=..\..\include\cppunit\SynchronizedObject.h
# End Source File
# Begin Source File
+SOURCE=.\Test.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\cppunit\Test.h
# End Source File
# Begin Source File
@@ -226,6 +230,14 @@ SOURCE=..\..\include\cppunit\TestCase.h
# End Source File
# Begin Source File
+SOURCE=.\TestComposite.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\cppunit\TestComposite.h
+# End Source File
+# Begin Source File
+
SOURCE=.\TestFailure.cpp
# End Source File
# Begin Source File
@@ -238,10 +250,26 @@ SOURCE=..\..\include\cppunit\TestFixture.h
# End Source File
# Begin Source File
+SOURCE=.\TestLeaf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\cppunit\TestLeaf.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\cppunit\TestListener.h
# End Source File
# Begin Source File
+SOURCE=.\TestPath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\cppunit\TestPath.h
+# End Source File
+# Begin Source File
+
SOURCE=.\TestResult.cpp
# End Source File
# Begin Source File
@@ -342,10 +370,6 @@ SOURCE=.\TestRunner.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\include\cppunitui\text\TestRunner.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\cppunit\TextTestRunner.h
# End Source File
# End Group