From: abn Date: Thu, 14 Apr 2016 09:17:26 +0000 (+0200) Subject: Test scenario playback made cleaner and less path dependent. X-Git-Tag: V8_1_0b1~25^2~5 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=5d20e3407611c56597173037d1ebb118659a4f8d;p=modules%2Fmed.git Test scenario playback made cleaner and less path dependent. This requires GUI branch [abn/exec_sig] --- diff --git a/src/MEDCalc/gui/DatasourceController.cxx b/src/MEDCalc/gui/DatasourceController.cxx index 31a82b48b..ccfe685b2 100644 --- a/src/MEDCalc/gui/DatasourceController.cxx +++ b/src/MEDCalc/gui/DatasourceController.cxx @@ -122,6 +122,11 @@ DatasourceController::addDatasource(const char* filename) event->eventtype = DatasourceEvent::EVENT_ADD_DATASOURCE; event->objectalias = filename; emit datasourceSignal(event); +//#ifdef MED_WITH_QTTESTING +// _dirtyAddDataSource = true; +// while(_dirtyAddDataSource) +// QApplication::processEvents(); +//#endif } // After above data source creation, python console emits a signal, forwarded by workspace, to update the GUI void @@ -138,6 +143,10 @@ DatasourceController::updateTreeViewWithNewDatasource(const MEDCALC::DatasourceH // update Object browser _salomeModule->getApp()->updateObjectBrowser(true); + +//#ifdef MED_WITH_QTTESTING +// _dirtyAddDataSource = false; +//#endif } void DatasourceController::OnAddDatasource() diff --git a/src/MEDCalc/gui/MEDModule.cxx b/src/MEDCalc/gui/MEDModule.cxx index b76c6ca87..7b8ffb2e1 100644 --- a/src/MEDCalc/gui/MEDModule.cxx +++ b/src/MEDCalc/gui/MEDModule.cxx @@ -44,13 +44,16 @@ #include "PVViewer_ViewModel.h" #endif +#include + #include //! The only instance of the reference to engine MED_ORB::MED_Gen_var MEDModule::myEngine; MEDModule::MEDModule() : - SalomeApp_Module("MED"), _studyEditor(0), _datasourceController(0), _workspaceController(0), _presentationController(0), _processingController(0) + SalomeApp_Module("MED"), _studyEditor(0), _datasourceController(0), _workspaceController(0), + _presentationController(0), _processingController(0) { // Note also that we can't use the getApp() function here because // the initialize(...) function has not been called yet. @@ -90,6 +93,15 @@ MEDModule::init() } } +//void MEDModule::onEventLoopStarted() +//{ +// if(!getApp()->isMainEventLoopStarted()) +// { +// QTimer::singleShot(100, this, SLOT(onEventLoopStarted())); +// return; +// } +//} + void MEDModule::initialize( CAM_Application* app ) { @@ -180,6 +192,10 @@ MEDModule::activateModule( SUIT_Study* theStudy ) _presentationController->showDockWidgets(true); //this->setDockLayout(StandardApp_Module::DOCKLAYOUT_LEFT_VLARGE); + // Mark the start of the main event loop - important for test playback: +// QObject::connect(getApp(), SIGNAL(activated(SUIT_Application *)), this, SLOT(onEventLoopStarted(SUIT_Application *))); +// QTimer::singleShot(0, this, SLOT(onEventLoopStarted())); + // return the activation status return bOk; } @@ -370,5 +386,12 @@ MEDModule::onDblClick(const QModelIndex& index) void MEDModule::requestSALOMETermination() const { + STDLOG("Requesting SALOME termination!!"); SUIT_Session::session()->closeSession( SUIT_Session::DONT_SAVE, 1 ); // killServers = True } + + +//bool MEDModule::hasMainEventLoopStarted() const +//{ +// return _eventLoopStarted; +//} diff --git a/src/MEDCalc/gui/MEDModule.hxx b/src/MEDCalc/gui/MEDModule.hxx index 12017f7be..4a2e01851 100644 --- a/src/MEDCalc/gui/MEDModule.hxx +++ b/src/MEDCalc/gui/MEDModule.hxx @@ -85,6 +85,8 @@ public: void requestSALOMETermination() const; +// bool hasMainEventLoopStarted() const; + public slots: virtual bool activateModule(SUIT_Study* theStudy); virtual bool deactivateModule(SUIT_Study* theStudy); diff --git a/src/MEDCalc/gui/TestController.cxx b/src/MEDCalc/gui/TestController.cxx index 9f2bc8dbd..78bb46dd2 100644 --- a/src/MEDCalc/gui/TestController.cxx +++ b/src/MEDCalc/gui/TestController.cxx @@ -45,11 +45,22 @@ #include #include #include +#include + +class PlayTestEvent: public QEvent { +public: + PlayTestEvent(QEvent::Type type, const std::string & filename): QEvent(type), _filename(filename) {} + virtual ~PlayTestEvent() {} + const std::string _filename; +}; TestController::TestController(MEDModule* mod): _salomeModule(mod), _desk(SUIT_Session::session()->activeApplication()->desktop()), - _tester(0), _lock_action(0) + _tester(0), _lock_action(0), + _quitEventType(QEvent::registerEventType()), + _playEventType(QEvent::registerEventType()), + _aboutToPlayTest(false) { STDLOG("Creating a TestController"); _tester = new pqTestUtility(_desk); @@ -120,19 +131,12 @@ void TestController::onPlayTest() _tester->playTests(fileName); } -void TestController::onPlayTestScenario() -{ - STDLOG("About to play test " << _test_scenario.toStdString()); - _tester->playTests(_test_scenario); - STDLOG("Done playing test " << _test_scenario.toStdString()); -} - -void TestController::onLockViewSize() +void TestController::onLockViewSize() const { pqTestingReaction::lockViewSize(_lock_action->isChecked()); } -void TestController::onTakeSnapshot() +void TestController::onTakeSnapshot() const { pqSaveScreenshotReaction::saveScreenshot(); } @@ -140,10 +144,10 @@ void TestController::onTakeSnapshot() void TestController::onRequestTermination() { // Check if test playing - if (_tester->playingTest()) + if (_tester->playingTest() || _aboutToPlayTest) { - STDLOG("Termination requested, but test still playing ..."); - QTimer::singleShot(200, this, SLOT(onRequestTermination())); + QEvent * e = new QEvent((QEvent::Type)_quitEventType); + QApplication::postEvent(this, e); } else { @@ -151,6 +155,38 @@ void TestController::onRequestTermination() } } +void +TestController::customEvent(QEvent * event) +{ + if (event->type() == _quitEventType) + { + if(!_salomeModule->getApp()->isMainEventLoopStarted()) + // Repost (=delay) + QApplication::postEvent(this, new QEvent((QEvent::Type)_quitEventType)); + else + onRequestTermination(); + } + else if (event->type() == _playEventType) + { + PlayTestEvent * e = dynamic_cast(event); + if (e) + { +// // Wait for main event loop to start: + if(!_salomeModule->getApp()->isMainEventLoopStarted()) + // Repost (=delay) + QApplication::postEvent(this, new PlayTestEvent((QEvent::Type)_playEventType, e->_filename)); + else + { + STDLOG("About to play test " << e->_filename); + _tester->playTests(e->_filename.c_str()); + _aboutToPlayTest = false; + STDLOG("Done playing test " << e->_filename); + } + } + } + else + { QObject::customEvent(event); } +} void TestController::processWorkspaceEvent(const MEDCALC::MedEvent* event) @@ -159,13 +195,15 @@ TestController::processWorkspaceEvent(const MEDCALC::MedEvent* event) /* [ABN] Post an event. Indeed, calling the function directly would prevent the proper refresh of the * GUI which also needs to go through the MED event loop (WorkspaceController::processWorkspaceEvent) */ - _test_scenario = QString(event->filename); - QTimer::singleShot(100, this, SLOT(onPlayTestScenario())); + _aboutToPlayTest = true; // to prevent an early quit! + PlayTestEvent * e = new PlayTestEvent((QEvent::Type)_playEventType, std::string(event->filename)); + QApplication::postEvent(this, e); } else if ( event->type == MEDCALC::EVENT_QUIT_SALOME ) { // [ABN] again: post as an event to give a chance to other events (piled up by test // scenarios for example) to execute: - QTimer::singleShot(200, this, SLOT(onRequestTermination())); + QEvent * e = new QEvent((QEvent::Type)_quitEventType); + QApplication::postEvent(this, e); } } diff --git a/src/MEDCalc/gui/TestController.hxx b/src/MEDCalc/gui/TestController.hxx index 7ce0b7bf3..9f5acfd6f 100644 --- a/src/MEDCalc/gui/TestController.hxx +++ b/src/MEDCalc/gui/TestController.hxx @@ -40,14 +40,19 @@ public: void createActions(); + + +protected: + virtual void customEvent(QEvent * event); + public slots: void processWorkspaceEvent(const MEDCALC::MedEvent* event); void onRecordTest(); void onPlayTest(); - void onPlayTestScenario(); - void onLockViewSize(); - void onTakeSnapshot(); +// void onPlayTestFile(); + void onLockViewSize() const; + void onTakeSnapshot() const; void onRequestTermination(); protected: @@ -56,7 +61,12 @@ protected: pqTestUtility * _tester; QAction * _lock_action; - QString _test_scenario; + +private: + const int _playEventType; + const int _quitEventType; + + bool _aboutToPlayTest; }; #endif /* SRC_MEDCALC_GUI_TESTCONTROLLER_HXX_ */ diff --git a/src/MEDCalc/test/CMakeLists.txt b/src/MEDCalc/test/CMakeLists.txt index c17548bd2..2a1326e09 100644 --- a/src/MEDCalc/test/CMakeLists.txt +++ b/src/MEDCalc/test/CMakeLists.txt @@ -32,6 +32,10 @@ SET(_test_baselines baselines/test_scalarmap.png ) +SET(_test_files + medfiles/test_scalarmap.med +) + # Test rules - the test MEDCalcQtTesting must be run after install (since it starts SALOME) ADD_TEST(MEDCalcQtTesting ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_qttesting.py) @@ -41,3 +45,4 @@ SALOME_INSTALL_SCRIPTS(${CMAKE_CURRENT_BINARY_DIR}/medcalc_testutils.py ${SALOME INSTALL(FILES ${_test_scenarii} DESTINATION ${SALOME_MED_INSTALL_RES_DATA}/tests/scenarios) INSTALL(FILES ${_test_baselines} DESTINATION ${SALOME_MED_INSTALL_RES_DATA}/tests/baselines) +INSTALL(FILES ${_test_files} DESTINATION ${SALOME_MED_INSTALL_RES_DATA}/tests/medfiles) diff --git a/src/MEDCalc/test/medcalc_testutils.py.in b/src/MEDCalc/test/medcalc_testutils.py.in index 59880a57f..61fe9d124 100644 --- a/src/MEDCalc/test/medcalc_testutils.py.in +++ b/src/MEDCalc/test/medcalc_testutils.py.in @@ -34,3 +34,8 @@ def GetScenarioDir(): def GetBaselineDir(): relativeDir = "@SALOME_MED_INSTALL_RES_DATA@/tests/baselines" return os.path.join(__getRootDir(), relativeDir) + +def GetMEDFileDir(): + relativeDir = "@SALOME_MED_INSTALL_RES_DATA@/tests/medfiles" + return os.path.join(__getRootDir(), relativeDir) + diff --git a/src/MEDCalc/test/medfiles/test_scalarmap.med b/src/MEDCalc/test/medfiles/test_scalarmap.med new file mode 100644 index 000000000..063a41dce Binary files /dev/null and b/src/MEDCalc/test/medfiles/test_scalarmap.med differ diff --git a/src/MEDCalc/test/scenarios/test_scalarmap.xml b/src/MEDCalc/test/scenarios/test_scalarmap.xml index edbc38fb4..42a7210e9 100644 --- a/src/MEDCalc/test/scenarios/test_scalarmap.xml +++ b/src/MEDCalc/test/scenarios/test_scalarmap.xml @@ -3,7 +3,7 @@ - + diff --git a/src/MEDCalc/test/test_qttesting.py b/src/MEDCalc/test/test_qttesting.py index 390afe5fe..165f93978 100644 --- a/src/MEDCalc/test/test_qttesting.py +++ b/src/MEDCalc/test/test_qttesting.py @@ -18,7 +18,7 @@ # # Author: A. Bruneton (CEA) -import unittest, os +import unittest, os, shutil from posixpath import basename class MEDGUITest(unittest.TestCase): @@ -42,30 +42,22 @@ class MEDGUITest(unittest.TestCase): """ Return name of the test being currently executed. """ return self.id().split(".")[-1] - def launchSalomeWithScript(self, scriptname, baseline): + def launchSalomeWithScript(self, scriptname): """ TODO: review this - what is the nicest way to launch SALOME GUI from a Python script? """ import shutil, subprocess from medcalc_testutils import GetScriptDir # TODO: review this! salomeCommand = os.path.join(os.environ.get("KERNEL_ROOT_DIR", ""), "bin", "salome", "runSalome.py") + args = "args:%s" % self._tmpDir pth = os.path.join(GetScriptDir(), scriptname) - # Remove a potentially already present image file from the tmp directory: - gen_image = os.path.join("/tmp", baseline) - try: - shutil.rmtree(gen_image) - except OSError: - pass # Launch SALOME with the test script: - status = subprocess.call([salomeCommand, pth]) + status = subprocess.call([salomeCommand, pth, args]) if status: raise Exception("SALOME exited abnormally for this test!") - try: - # Move generated image to the temporary test directory - ideally test should produce image there directly ... - shutil.move(gen_image, self._tmpDir) - except IOError: - raise Exception("Test script didn't produce expected image '%s'!" % gen_image) def compareSnapshot(self, basename): + """ Compare the screenshot in the current temporary test directory with the reference baseline. + Assert if not matching. """ import filecmp from medcalc_testutils import GetBaselineDir @@ -82,13 +74,31 @@ class MEDGUITest(unittest.TestCase): self.assertTrue(ret, "[%s] -- Failed screenshot equality, or unable to open baseline file - directory is kept alive: %s" % (self.getTestName(), self._tmpDir)) return ret + def prepareScenario(self, scenario, baseline, med_file): + """ Copy scenario to current temporary test dir and substitute paths inside """ + from medcalc_testutils import GetScenarioDir, GetMEDFileDir + scen_path = os.path.join(GetScenarioDir(), scenario) + scen_pth2 = os.path.join(self._tmpDir, scenario) + try: + shutil.copy(scen_path, scen_pth2) + except IOError: + raise Exception("Could not copy test scenario '%s' to local test directory!" % scen_path) + with open(scen_pth2,'r') as f: + filedata = f.read() + filedata = filedata.replace("/tmp/%s" % baseline, "%s/%s" % (self._tmpDir, baseline)) + filedata = filedata.replace("/tmp/%s" % med_file, os.path.join(GetMEDFileDir(), med_file)) + with open(scen_pth2,'w') as f: + f.write(filedata) + ## ## Now the tests themselves ## - def testScalarMap(self): baseline = "test_scalarmap.png" - self.launchSalomeWithScript("test_scalarmap.py", baseline) + med_file = "test_scalarmap.med" # will change + scenario = "test_scalarmap.xml" + self.prepareScenario(scenario, baseline, med_file) + self.launchSalomeWithScript("test_scalarmap.py") self.compareSnapshot(baseline) diff --git a/src/MEDCalc/test/test_scalarmap.py b/src/MEDCalc/test/test_scalarmap.py index ddf508ee3..0f6b0694d 100644 --- a/src/MEDCalc/test/test_scalarmap.py +++ b/src/MEDCalc/test/test_scalarmap.py @@ -23,7 +23,7 @@ This script is to be passed as an argument of the ./salome command and will be e Python console. """ -import os +import os, sys import SalomePyQt from medcalc_testutils import GetScenarioDir @@ -31,6 +31,7 @@ sgPyQt = SalomePyQt.SalomePyQt() sgPyQt.activateModule('MED') import medcalc # After module activation !! -medcalc.PlayQtTestingScenario(os.path.join(GetScenarioDir(), 'test_scalarmap.xml')) +localTestDir = sys.argv[1] +medcalc.PlayQtTestingScenario(os.path.join(localTestDir, 'test_scalarmap.xml')) -medcalc.RequestSALOMETermination() # not equivalent to quit()! +#medcalc.RequestSALOMETermination() # not equivalent to quit()!