import sys import numpy as np import unittest from unittest.mock import mock_open, patch import webbrowser import logging from unittest.mock import MagicMock from PyQt5 import QtGui, QtWidgets # set up import paths import path_prepare from sas.qtgui.UnitTesting.TestUtils import QtSignalSpy from sas.sascalc.fit.AbstractFitEngine import FResult from sas.sascalc.fit.AbstractFitEngine import FitData1D from sasmodels.sasview_model import load_standard_models from sas.qtgui.Plotting.PlotterData import Data1D import sas.qtgui.Utilities.GuiUtils as GuiUtils # Local from sas.qtgui.Utilities.GridPanel import BatchOutputPanel if not QtWidgets.QApplication.instance(): app = QtWidgets.QApplication(sys.argv) class BatchOutputPanelTest(unittest.TestCase): '''Test the batch output dialog''' def setUp(self): '''Create the dialog''' # dummy perspective class dummy_manager(object): _parent = QtWidgets.QWidget() def communicator(self): return GuiUtils.Communicate() def communicate(self): return GuiUtils.Communicate() self.widget = BatchOutputPanel(parent=dummy_manager(), output_data=self.output_for_test()) test_table = {"p1":[1,2,3], "p2":[4,5,None], "":["a",credits,], "":[]} def tearDown(self): '''Destroy the GUI''' self.widget.close() self.widget = None def output_for_test(self): ''' define DATA1D structure for testing''' # dummy parameter set m = None for m in load_standard_models(): if m.name == "core_shell_ellipsoid": model = m() self.assertIsNotNone(m) data = Data1D(x=[1,2], y=[3,4], dx=[0.1, 0.1], dy=[0.,0.]) fit_data = FitData1D(x=[1,2], y=[3,4], data=data) param_list = ['sld_shell', 'sld_solvent'] output = FResult(model=model, data=fit_data, param_list=param_list) output.sas_data = data output.theory = np.array([0.1,0.2]) output.pvec = np.array([0.1, 0.02]) output.residuals = np.array([0.01, 0.02]) output.fitness = 9000.0 output.fitter_id = 200 output.stderr = [0.001, 0.001] output_data = [[output],[output]] return output_data def testDefaults(self): '''Test the GUI in its default state''' self.assertIsInstance(self.widget, QtWidgets.QMainWindow) # Default title self.assertEqual(self.widget.windowTitle(), "Batch Fitting Results") # non-modal window self.assertFalse(self.widget.isModal()) def testActionLoadData(self): '''Test CSV data loader''' test_csv = mock_open(read_data = ("""\ File generated by SasView\n Chi2,Data,scale,background,radius_equat_core,x_core,thick_shell,x_polar_shell,sld_core,sld_shell,sld_solvent,theta,phi,\n 1917.8,cyl_400_40.txt,1,0.001,20,3,30,1,-85.088,-97.636,-92.797,0,0,\n 2.6169,cyl_400_20.txt,1,0.001,20,3,30,1,914.64,906.09,905.67,0,0,\n """)) logging.info = MagicMock() self.widget.setupTableFromCSV = MagicMock() # No filename given QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[""]) self.widget.actionLoadData() # Assure parser wasn't called and logging got a message self.assertTrue(logging.info.called_once()) self.assertIn("No data", logging.info.call_args[0][0]) # Filename given QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value="test") with patch('builtins.open', test_csv): self.widget.actionLoadData() # Assure parser was called self.assertTrue(self.widget.actionLoadData) self.widget.setupTableFromCSV.assert_called_once() self.assertIn("File generated by SasView", self.widget.setupTableFromCSV.call_args[0][0][0]) def notestPlotFits(self): '''Test plot generation from selected table rows''' # mock tested calls #GuiUtils.Communicate.plot spy_plot_signal = QtSignalSpy(self.widget.communicate, self.widget.communicate().plotFromFilenameSignal) # Select row #1 self.widget.tblParams.selectRow(0) QtWidgets.QApplication.processEvents() # See that the signal was emitted self.assertEqual(spy_plot_signal.count(), 1) self.assertIn("ddd", str(spy_plot_signal.called()[0]['args'][0])) def testDataFromTable(self): '''Test dictionary generation from data''' params = self.widget.dataFromTable(self.widget.tblParams) self.assertEqual(len(params), 13) self.assertEqual(params['Chi2'][0], '9000') self.assertEqual(params['Data'][1], '') self.assertEqual(params['sld_solvent'][1], '0.02') def testActionSendToExcel(self): '''Test Excel bindings''' pass def testActionSaveFile(self): '''Test file save''' self.widget.writeBatchToFile = MagicMock() # user cancels dialog QtWidgets.QFileDialog.getSaveFileName = MagicMock(return_value=("","BOOP")) # write not called self.widget.actionSaveFile() self.widget.writeBatchToFile.assert_not_called() # user chooses proper name QtWidgets.QFileDialog.getSaveFileName = MagicMock(return_value=("plop","BOOP")) # write called self.widget.actionSaveFile() self.widget.writeBatchToFile.assert_called_once() def testSetupTableFromCSV(self): '''Test generation of grid table rows from a CSV file''' pass