[Cppunit-cvs] cppunit2/src/opentest SConscript,NONE,1.1 texttestdriver.cpp,NONE,1.1
Brought to you by:
blep
From: Baptiste L. <bl...@us...> - 2005-02-28 22:12:14
|
Update of /cvsroot/cppunit/cppunit2/src/opentest In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32753/src/opentest Added Files: SConscript texttestdriver.cpp Log Message: * moved texttestdriver.h class implementations into a .cpp --- NEW FILE: SConscript --- Import( 'env' ) env = env.Copy( LIBPATH = '#libs' ) opentest_sources=""" texttestdriver.cpp """.split() static_lib = env.StaticLibrary( target='opentest', source=opentest_sources ) #shared_lib = env.SharedLibrary( target='cpput', # source=cpput_sources ) libs_dir='#libs' bin_dir='#bin' env.Install( libs_dir, static_lib ) --- NEW FILE: texttestdriver.cpp --- #include <opentest/texttestdriver.h> #include <iostream> // for progress namespace OpenTest { // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class TestDriverTestPlan // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// TestPlanEntryPtrEnum TestDriverTestPlan::entries() const { return CppTL::Enum::anyContainer( entries_ ); } void TestDriverTestPlan::add( const TestPlanEntryPtr &entry ) { entries_.push_back( entry ); } // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class TestResult // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// TestResult::TestResult( TestPlanEntryId id, TestId test ) : id_( id ) , test_( test ) { } TestPlanEntryId TestResult::id() const { return id_; } TestId TestResult::test() const { return test_; } const Properties & TestResult::result() const { return result_; } Properties & TestResult::result() { return result_; } // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class TestDriverTestPlanEntry // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// TestDriverTestPlanEntry::TestDriverTestPlanEntry( TestPlanEntryId id, TestId test, const Properties &configuration ) : id_( id ) , test_( test ) , configuration_( configuration ) { } TestPlanEntryId TestDriverTestPlanEntry::id() const { return id_; } /// Test to run TestId TestDriverTestPlanEntry::test() const { return test_; } /// Used to pass configuration data to the test runner or the test itself const Properties & TestDriverTestPlanEntry::configuration() const { return configuration_; } // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class TextTestDriver // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// TextTestDriver::TextTestDriver( TestRunner &runner ) : runner_( runner ) , nextTestId_( 0 ) { runner_.declareTests( *this ); std::cout << "Declared suites: " << suites_.size() << "\n" << "Declared tests: " << tests_.size() << std::endl; } bool TextTestDriver::run() { if ( testsToRun_.empty() ) testsToRun_ = tests_; TestDriverTestPlan plan; Tests::const_iterator itTest = testsToRun_.begin(); unsigned int entryId = 0; for ( ; itTest != testsToRun_.end(); ++itTest ) plan.add( TestPlanEntryPtr( new TestDriverTestPlanEntry( ++entryId, *itTest, Properties() ) ) ); runner_.runTests( plan, *this, Properties() ); outputFailures(); return failures_.empty(); } TestId TextTestDriver::beginSuite( const CppTL::ConstString &name, const Properties &data ) { TestId id = nextTestId(); declareTestOrSuite( id, name, data ); declaratorParentSuites_.push_back( id ); suites_.insert( id ); return id; } TestId TextTestDriver::addTest( const CppTL::ConstString &name, const Properties &data ) { TestId id = nextTestId(); declareTestOrSuite( id, name, data ); tests_.insert( id ); return id; } void TextTestDriver::endSuite() { declaratorParentSuites_.pop_back(); } void TextTestDriver::declareTestOrSuite( TestId id, const CppTL::ConstString &name, const Properties &data ) { InternalTestInfo info( id, name, data, declaratorParentSuites_ ); testInfos_.insert( TestInfos::value_type( id, info ) ); if ( declaratorParentSuites_.size() > 0 ) { TestId parentId = declaratorParentSuites_.back(); getTestInfo(parentId).children_.push_back( id ); } } TestId TextTestDriver::nextTestId() { return ++nextTestId_; } void TextTestDriver::startTestRun() { results_.clear(); successes_.clear(); failures_.clear(); } void TextTestDriver::startTest( const TestPlanEntry &testEntry ) { TestResult result( testEntry.id(), testEntry.test() ); // should add descriptive test data first result.result().mergeReplacingExisting( testEntry.configuration() ); results_.push_back( result ); const unsigned int maxParent = 1; std::cout << "Testing '" << getTestPath( testEntry.test(), maxParent ) << "' : "; std::cout.flush(); } void TextTestDriver::mergeInTestResult( const TestPlanEntry &testEntry, const Properties &result ) { results_.back().result()["result"].asProperties().mergeReplacingExisting( result ); } void TextTestDriver::mergeInTestResult( const TestPlanEntry &testEntry, const PropertyPath &path, const Value &value ) { results_.back().result()["result"][path] = value; } void TextTestDriver::appendToTestResult( const TestPlanEntry &testEntry, const PropertyPath &path, const Value &value ) { results_.back().result()["result"][path].append( value ); } void TextTestDriver::endTest( const TestPlanEntry &testEntry ) { const Properties &result = results_.back().result(); PropertiesAccessor status = result.accessor()["result"]["status"]; bool succeeded = status.getValue( "success", false ).asBool(); CppTL::ConstString statusInfo = succeeded ? "OK" : "FAIL"; if ( succeeded ) successes_.push_back( results_.size() - 1 ); else failures_.push_back( results_.size() - 1 ); CppTL::ConstString resultType = status.getValue( "type", "" ).asString(); if ( !resultType.empty() ) statusInfo += " (" + resultType + ")"; std::cout << statusInfo << std::endl; std::cout.flush(); // std::cout << result.toString() << std::endl; } void TextTestDriver::endTestRun() { } bool TextTestDriver::shouldStopTestRun() { return false; } const TextTestDriver::InternalTestInfo & TextTestDriver::getTestInfo( TestId test ) const { TestInfos::const_iterator it = testInfos_.find( test ); if ( it == testInfos_.end() ) throw std::invalid_argument( "TextTestDriver::getTestInfo() : bad TestId." ); return it->second; } TextTestDriver::InternalTestInfo & TextTestDriver::getTestInfo( TestId test ) { TestInfos::iterator it = testInfos_.find( test ); if ( it == testInfos_.end() ) throw std::invalid_argument( "TextTestDriver::getTestInfo() : bad TestId." ); return it->second; } void TextTestDriver::outputFailures() { if ( failures_.empty() ) { std::cout << "All " << testsToRun_.size() << " tests passed..." << std::endl; return; } TestResultIndexes::const_iterator failuresIt = failures_.begin(); for ( ; failuresIt != failures_.end(); ++failuresIt ) { // @todo update to new result properties structure const TestResult &testResult = results_.at( *failuresIt ); PropertiesAccessor info = testResult.result().accessor(); Properties::ValueEnum enumFaults = info["result/faults"].listValues(); while ( enumFaults.hasNext() ) { // @todo check is properties => schema check ? Value fault = enumFaults.next(); reportFailure( testResult, fault.asProperties(), false ); } Properties::ValueEnum enumAssertions = info["result/assertions"].listValues(); while ( enumAssertions.hasNext() ) { // @todo check is properties => schema check ? Value assertion = enumAssertions.next(); reportFailure( testResult, assertion.asProperties(), true ); } /* PropertiesAccessor locationInfo = info["result"]["status"]["location"]; if ( locationInfo.isValid() ) { std::cout << locationInfo.getValue("file").asString() << "(" << locationInfo.getValue("line").asInt() << ") : "; } else { std::cout << "Unknown failure location : "; } std::cout << getTestPath( testResult.test() ) << std::endl; CppTL::ConstString failureType = info["result"]["status"].getValue("type","").asString(); if ( !failureType.empty() ) std::cout << "Failure type : " << failureType << std::endl; CppTL::ConstString message = info["result"]["status"].getValue("message","").asString(); if ( !message.empty() ) std::cout << message << std::endl; */ std::cout << "Failures: " << failures_.size() << ", "; std::cout << "Tested: " << testsToRun_.size() << std::endl; } } void TextTestDriver::reportFailure( const TestResult &testResult, const Properties &failure, bool isAssertion ) { if ( failure.has( "location") ) { if ( failure.has("location/file") ) { std::cout << failure["location/file"].asString() << "(" << failure["location/line"].asInt() << ") "; } if ( failure.has("location/function") ) std::cout << "{" << failure["location/function"].asString() << "} "; std::cout << " : "; } std::cout << getTestPath( testResult.test() ) << std::endl; CppTL::ConstString failureType = failure.getValue( "failure_type", isAssertion ? "assertion" : "fault" ).asString(); std::cout << "Failure type : " << failureType << std::endl; Properties::ValueEnum enumMessages = failure.accessor()["messages"].listValues(); if ( enumMessages.hasNext() ) std::cout << "Messages:\n"; while ( enumMessages.hasNext() ) { // @todo check type CppTL::ConstString message = enumMessages.next().asString(); std::cout << message << std::endl; } Properties::ValueEnum enumLogs = failure.accessor()["logs"].listValues(); if ( enumLogs.hasNext() ) std::cout << "Log:\n"; while ( enumLogs.hasNext() ) { // @todo check type CppTL::ConstString log = enumLogs.next().asString(); std::cout << log << std::endl; } std::cout << "Failure tree:" << failure.toString() << std::endl; } CppTL::ConstString TextTestDriver::getTestPath( TestId test, unsigned int maxParent ) const { CppTL::ConstString path; const InternalTestInfo &info = getTestInfo( test ); path = "/" + info.name_; if ( info.parents_.empty() ) return path; bool isPartialPath = maxParent < info.parents_.size(); for ( unsigned int index = info.parents_.size()-1; index != -1 && maxParent-- >0; --index ) { const InternalTestInfo &parentInfo = getTestInfo( info.parents_[index] ); path = "/" + parentInfo.name_ + path; } if ( isPartialPath ) path = ".." + path; return path; } // Implementation of TestInfoExplorer // ////////////////////////////////////////////////////////////////// namespace Impl { struct IsTestSuiteOrTestCaseFilter { IsTestSuiteOrTestCaseFilter( bool keepSuite ) : keepSuite_( keepSuite ) { } bool operator()( const TestInfo &info ) const { return info.isTestSuite() == keepSuite_; } bool keepSuite_; }; struct TestId2TestInfoAdapator { typedef TestInfo result_type; TestId2TestInfoAdapator( const TestInfoHolder &holder ) : holder_( holder ) { } TestInfo operator()( TestId id ) const { return TestInfo( holder_, id ); } const TestInfoHolder &holder_; }; } // namespace Impl TestInfoEnumerator TextTestDriver::getAllTestCases() const { return CppTL::Enum::anyTransform( CppTL::Enum::container( tests_, CppTL::Type<TestId>() ), Impl::TestId2TestInfoAdapator( *this ) ); } TestInfoEnumerator TextTestDriver::getAllTestSuites() const { return CppTL::Enum::anyTransform( CppTL::Enum::container( suites_, CppTL::Type<TestId>() ), Impl::TestId2TestInfoAdapator( *this ) ); } TestInfo TextTestDriver::getRootTestSuite() const { TestId id; if ( !tests_.empty() ) id = *(tests_.begin()); else if ( !suites_.empty() ) id = *(suites_.begin()); else throw std::logic_error( "TextTestDriver::getRootTestSuite(): no suite defined." ); while ( !getTestInfo(id).parents_.empty() ) id = *(getTestInfo(id).parents_.begin()); return TestInfo( *this, id ); } // Implementation of TestInfoHolder // ////////////////////////////////////////////////////////////////// const String & TextTestDriver::getTestName( TestId id ) const { return getTestInfo(id).name_; } PropertiesAccessor TextTestDriver::getTestDescription( TestId id ) const { return getTestInfo(id).info_.accessor()["description"]; } PropertiesAccessor TextTestDriver::getTestInput( TestId id ) const { return getTestInfo(id).info_.accessor()["input"]; } bool TextTestDriver::isTestSuite( TestId id ) const { return suites_.count(id) > 0; } TestInfoEnumerator TextTestDriver::getTestChildren( TestId id ) const { return CppTL::Enum::anyTransform( CppTL::Enum::container( getTestInfo(id).children_ ), Impl::TestId2TestInfoAdapator( *this ) ); } TestInfoEnumerator TextTestDriver::getTestParents( TestId id ) const { return CppTL::Enum::anyTransform( CppTL::Enum::container( getTestInfo(id).parents_ ), Impl::TestId2TestInfoAdapator( *this ) ); } // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class TestInfo // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// TestInfo::TestInfo( const TestInfoHolder &holder, TestId id ) : id_( id ) , holder_( holder ) { } const String & TestInfo::getName() const { return holder_.getTestName( id_ ); } PropertiesAccessor TestInfo::getDescription() const { return holder_.getTestDescription( id_ ); } bool TestInfo::isTestSuite() const { return holder_.isTestSuite( id_ ); } bool TestInfo::isTestCase() const { return !isTestSuite(); } TestInfoEnumerator TestInfo::getParents() const { return holder_.getTestParents( id_ ); } PropertiesAccessor TestInfo::getInput() const { return holder_.getTestInput( id_ ); } TestInfoEnumerator TestInfo::getChildren() const { return holder_.getTestChildren( id_ ); } TestInfoEnumerator TestInfo::getChildTestSuites() const { return CppTL::Enum::anyFilter( getChildren(), Impl::IsTestSuiteOrTestCaseFilter(true) ); } TestInfoEnumerator TestInfo::getChildTestCases() const { return CppTL::Enum::anyFilter( getChildren(), Impl::IsTestSuiteOrTestCaseFilter(false) ); } } // namespace OpenTest |