From 2a2b4c9e5b092e19ddf7ec0e73a638999fe24d59 Mon Sep 17 00:00:00 2001 From: asl Date: Wed, 14 Oct 2015 12:23:38 +0300 Subject: [PATCH] custom test runner to run only a subset of complete test suite --- src/HYDRO_tests/CMakeLists.txt | 2 + src/HYDRO_tests/TestLib_Runner.cxx | 120 ++++++++++++++++++++++++ src/HYDRO_tests/TestLib_Runner.h | 40 ++++++++ src/HYDRO_tests/test_HYDROData_Main.cxx | 8 +- 4 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 src/HYDRO_tests/TestLib_Runner.cxx create mode 100644 src/HYDRO_tests/TestLib_Runner.h diff --git a/src/HYDRO_tests/CMakeLists.txt b/src/HYDRO_tests/CMakeLists.txt index cdd73573..bad92903 100644 --- a/src/HYDRO_tests/CMakeLists.txt +++ b/src/HYDRO_tests/CMakeLists.txt @@ -15,6 +15,7 @@ set(PROJECT_HEADERS test_HYDROGUI_ListModel.h TestViewer.h + TestLib_Runner.h ) set(PROJECT_SOURCES @@ -32,6 +33,7 @@ set(PROJECT_SOURCES test_HYDROGUI_ListModel.cxx TestViewer.cxx + TestLib_Runner.cxx ) add_definitions( diff --git a/src/HYDRO_tests/TestLib_Runner.cxx b/src/HYDRO_tests/TestLib_Runner.cxx new file mode 100644 index 00000000..5cf1089c --- /dev/null +++ b/src/HYDRO_tests/TestLib_Runner.cxx @@ -0,0 +1,120 @@ + +/** + @file + \brief Implementation of the custom runner allowing start a subset of tests +*/ + +#include +#include +#include +#include +#include + +/** + Conversion of the given string to lower-case + @param theStr the string to convert to lower-case + @return the converted string +*/ +std::string ToLower( const std::string& theStr ) +{ + std::string aStr = theStr; + std::transform( aStr.begin(), aStr.end(), aStr.begin(), ::tolower ); + return aStr; +} + +/** + Add a substring pattern to test runner + @param theSubstr the substring pattern to add +*/ +void TestLib_Runner::Add( const std::string& theSubstr ) +{ + mySubStrings.push_back( ToLower( theSubstr ) ); +} + +/** + Load the configuration file with substring patterns + @param theConfigFile the path to the configuration file + @return if the operation is successful +*/ +bool TestLib_Runner::Load( const std::string& theConfigFile ) +{ + std::ifstream anInput( theConfigFile.c_str() ); + bool isOK = anInput.is_open(); + if( !isOK ) + return false; + + std::string aLine; + while( std::getline( anInput, aLine ) ) + { + int aPos = aLine.find( "//" ); + if( aPos != std::string::npos ) + aLine.erase( aPos ); + + //trim + aLine.erase( 0, aLine.find_first_not_of( ' ' ) ); + aLine.erase( aLine.find_last_not_of( ' ' ) + 1 ); + + if( !aLine.empty() ) + Add( aLine ); + } + + return true; +} + +/** + Determine if the given test name is allowed by patterns + @param theTestName the test name + @return true if the test name is allowed +*/ +bool TestLib_Runner::IsAllowed( const std::string& theTestName ) const +{ + if( mySubStrings.empty() ) + return true; + + std::string aTestName = ToLower( theTestName ); + + std::list::const_iterator anIt = mySubStrings.begin(), aLast = mySubStrings.end(); + for( ; anIt!=aLast; ++anIt ) + if( aTestName.find( *anIt ) != std::string::npos ) + return true; + + return false; +} + + +/** + Determine list of tests allowed by patterns from the given CPPUnit tests tree + @param theRoot the root of the CPPUnit tests tree + @param theAllowedTests the returned vector of allowed tests names +*/ +void TestLib_Runner::GetTests( CPPUNIT_NS::Test* theRoot, std::list& theAllowedTests ) const +{ + for( int i=0, n=theRoot->getChildTestCount(); igetChildTestAt( i ); + std::string aName = aTest->getName(); + if( IsAllowed( aName ) ) + theAllowedTests.push_back( aName ); + else + GetTests( aTest, theAllowedTests ); + } +} + +/** + Run all necessary tests + @param theController the controller of the tests results +*/ +void TestLib_Runner::Run( CPPUNIT_NS::TestResult& theController ) +{ + std::list aTests; + GetTests( m_suite, aTests ); + std::list::const_iterator anIt = aTests.begin(), aLast = aTests.end(); + for( ; anIt!=aLast; ++anIt ) + { + std::string aTestPath = *anIt; + CPPUNIT_NS::TestPath aPath = m_suite->resolveTestPath( aTestPath ); + CPPUNIT_NS::Test* aTest = aPath.getChildTest(); + theController.runTest( aTest ); + } +} + diff --git a/src/HYDRO_tests/TestLib_Runner.h b/src/HYDRO_tests/TestLib_Runner.h new file mode 100644 index 00000000..1cf8dc26 --- /dev/null +++ b/src/HYDRO_tests/TestLib_Runner.h @@ -0,0 +1,40 @@ + +/** + @file + \brief Declaration of the custom runner allowing start a subset of tests +*/ + +#pragma once + +#include +#include + +#ifdef WIN32 + #pragma warning( disable: 4251 ) + #pragma warning( disable: 4275 ) +#endif + +/** + \class TestLib_Runner + \brief Implementation of the custom runner allowing start a subset of tests +*/ +class TestLib_Runner : public CPPUNIT_NS::TestRunner +{ +public: + void Add( const std::string& theSubstr ); + bool Load( const std::string& theConfigFile ); + void Run( CPPUNIT_NS::TestResult& theController ); + +protected: + void GetTests( CPPUNIT_NS::Test* theRoot, std::list& theAllowedTests ) const; + bool IsAllowed( const std::string& theTestName ) const; + +private: + std::list mySubStrings; ///< the list of substring patterns +}; + +#ifdef WIN32 + #pragma warning( default: 4251 ) + #pragma warning( default: 4275 ) +#endif + diff --git a/src/HYDRO_tests/test_HYDROData_Main.cxx b/src/HYDRO_tests/test_HYDROData_Main.cxx index 5b1367cb..52b58728 100644 --- a/src/HYDRO_tests/test_HYDROData_Main.cxx +++ b/src/HYDRO_tests/test_HYDROData_Main.cxx @@ -20,10 +20,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -57,12 +57,14 @@ int main( int argc, char* argv[] ) CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry(); // Add the top suite to the test runner - CppUnit::TestRunner runner; + TestLib_Runner runner; + QString aPath = qgetenv( "HYDRO_SRC_DIR" ) + "/src/tests.cfg"; + runner.Load( aPath.toStdString() ); runner.addTest( registry.makeTest() ); try { std::cout << "Running " << testPath; - runner.run( controller, testPath ); + runner.Run( controller ); std::cerr << std::endl; -- 2.39.2