summaryrefslogtreecommitdiff
path: root/src/cppunit
diff options
context:
space:
mode:
authorBaptiste Lepilleur <gaiacrtn@free.fr>2002-04-12 18:28:48 +0000
committerBaptiste Lepilleur <gaiacrtn@free.fr>2002-04-12 18:28:48 +0000
commited406a2966e62072fa6afaca8abc578db7c0c9fb (patch)
treeab8d2ffb462c3c955b2e339e8cc19f1a6be8bd0f /src/cppunit
parentfc9c76622b19adfcdebce682d9d49db8fb9336ef (diff)
downloadcppunit-ed406a2966e62072fa6afaca8abc578db7c0c9fb.tar.gz
Makefile.
Makefile.am: added examples/qt to tar ball release. * TODO: heavily updated. * contrib/msvc/CppUnit*.wwtpl: changed base class for unit test to TestFixture. * include/cppunit/Test.h: removed toString() method. Not used by the framework and source of confusions with getName(). Added getChildTestCount() and getChildTestAt(), introducing the composite pattern at top level. Added utility methods findTest() and findTestPath(). * src/cppunit/Test.cpp: added. Implementation of new utility methods. * include/cppunit/TestCase.h: * src/cppunit/TestCase.cpp: inherits TestLeaf. Removed toString(), run(void) and defaultResult(). Removed default constructor. * src/cppunit/TestCase.cpp: * src/cppunit/TestSuite.cpp: fixed some includes that used "" instead of <>. * include/cppunit/TestComposite.h: * src/cppunit/TestComposite.cpp: added. Common implementation of Test for composite tests (TestSuite). * include/cppunit/TestFailure.h: * src/cppunit/TestFailure.cpp: removed toString(). * include/cppunit/TestLeaf.h: * src/cppunit/TestLeaf.cpp: added. Common implementation of Test for single test (TestCase). * include/cppunit/TestListener.h: added TimingListener example to documentation. * include/cppunit/TestPath.h: * src/cppunit/TestPath.cpp: added. List of test traversed to access a test in the test hierarchy. * include/cppunit/TestRunner.h: added. Generic TestRunner. * src/cppunit/TestRunner.cpp: moved to TextTestRunner.cpp. Added new implementation of includecppunit/TestRunner.h. * include/cppunit/TestSuite.h: * src/cppunit/TestSuite.cpp: inherits TestComposite and implements new Test interface. Removed toString(). * src/cppunit/TextTestRunner.cpp: moved from TestRunner.cpp. Implementation of include/cppunit/ui/text/TestRunner.h. * include/cppunit/extensions/RepeatedTest.h: * src/cppunit/RepeatedTest.cpp: removed toString(). * include/cppunit/extensions/TestDecorator.h: inherits TestLeaf. Removed toString() * include/cppunit/XmlOutputter.h: * src/cppunit/XmlOutputter.cpp: * examples/cppunittest/XmlOutputterTest.cpp: * examples/cppunittest/XmlOutputterTest.h: XML outputter now escape node content. Add unit test for that bug (#540944). Added style sheet support. Modified XML structure: failure message as its own element. * src/msvc/testrunner/TestRunnerModel.h: * src/msvc/testrunner/TestRunnerModel.cpp: used Test::findTest() to find a test by name instead of using RTTI. Added toAnsiString() for convertion when compiling as UNICODE. * src/msvc/testrunner/TreeHierarchyDlg.h: * src/msvc/testrunner/TreeHierarchyDlg.cpp: used new composite interface of Test to explorer the test hierarchy instead of RTTI. * examples/cppunittest/TestPathTest.h: * examples/cppunittest/TestPathTest.cpp: added, unit tests for TestPath. * examples/cppunittest/TestCaseTest.h: * examples/cppunittest/TestCaseTest.cpp: added test for TestLeaf. * examples/cppunittest/TestSuiteTest.h: * examples/cppunittest/TestSuiteTest.cpp: added test for TestComposite and new Test interface.
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