source: sasview/src/sas/qtgui/Perspectives/Inversion/UnitTesting/InversionPerspectiveTest.py @ 72ecbdf2

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 72ecbdf2 was 72ecbdf2, checked in by krzywon, 3 years ago

Add a stop calculations button to P(r). Plus unit tests.

  • Property mode set to 100755
File size: 13.7 KB
Line 
1import time
2import unittest
3from unittest.mock import MagicMock
4
5from PyQt5 import QtGui, QtWidgets
6
7from sas.qtgui.Utilities.GuiUtils import *
8from sas.qtgui.Perspectives.Inversion.InversionPerspective import InversionWindow
9from sas.qtgui.Perspectives.Inversion.InversionUtils import WIDGETS
10from sas.qtgui.Plotting.PlotterData import Data1D
11
12import sas.qtgui.Utilities.GuiUtils as GuiUtils
13
14#if not QtWidgets.QApplication.instance():
15app = QtWidgets.QApplication(sys.argv)
16
17
18class dummy_manager(object):
19    HELP_DIRECTORY_LOCATION = "html"
20    communicate = Communicate()
21
22    def communicator(self):
23        return self.communicate
24
25
26class InversionTest(unittest.TestCase):
27    """ Test the Inversion Perspective GUI """
28
29    def setUp(self):
30        """ Create the InversionWindow """
31        self.widget = InversionWindow(dummy_manager())
32        self.widget.show()
33        self.fakeData1 = GuiUtils.HashableStandardItem("A")
34        self.fakeData2 = GuiUtils.HashableStandardItem("B")
35        reference_data1 = Data1D(x=[0.1, 0.2], y=[0.0, 0.0], dy=[0.0, 0.0])
36        reference_data1.filename = "Test A"
37        reference_data2 = Data1D(x=[0.1, 0.2], y=[0.0, 0.0], dy=[0.0, 0.0])
38        reference_data2.filename = "Test B"
39        GuiUtils.updateModelItem(self.fakeData1, reference_data1)
40        GuiUtils.updateModelItem(self.fakeData2, reference_data2)
41
42    def tearDown(self):
43        """ Destroy the InversionWindow """
44        self.widget.setClosable(False)
45        self.widget.close()
46        self.widget = None
47
48    def removeAllData(self):
49        """ Cleanup method to restore widget to its base state """
50        if len(self.widget.dataList) > 0:
51            remove_me = list(self.widget._dataList.keys())
52            self.widget.removeData(remove_me)
53
54    def baseGUIState(self):
55        """ Testing base state of Inversion """
56        # base class information
57        self.assertIsInstance(self.widget, QtWidgets.QWidget)
58        self.assertEqual(self.widget.windowTitle(), "P(r) Inversion Perspective")
59        self.assertFalse(self.widget.isClosable())
60        self.assertFalse(self.widget.isCalculating)
61        # mapper
62        self.assertIsInstance(self.widget.mapper, QtWidgets.QDataWidgetMapper)
63        self.assertNotEqual(self.widget.mapper.mappedSection(self.widget.dataList), -1)
64        # validators
65        self.assertIsInstance(self.widget.noOfTermsInput.validator(), QtGui.QIntValidator)
66        self.assertIsInstance(self.widget.regularizationConstantInput.validator(), QtGui.QDoubleValidator)
67        self.assertIsInstance(self.widget.maxDistanceInput.validator(), QtGui.QDoubleValidator)
68        self.assertIsInstance(self.widget.minQInput.validator(), QtGui.QDoubleValidator)
69        self.assertIsInstance(self.widget.maxQInput.validator(), QtGui.QDoubleValidator)
70        self.assertIsInstance(self.widget.slitHeightInput.validator(), QtGui.QDoubleValidator)
71        self.assertIsInstance(self.widget.slitWidthInput.validator(), QtGui.QDoubleValidator)
72        # model
73        self.assertEqual(self.widget.model.rowCount(), 22)
74        self.assertEqual(self.widget.model.columnCount(), 1)
75        self.assertEqual(self.widget.mapper.model(), self.widget.model)
76        # buttons
77        self.assertFalse(self.widget.calculateThisButton.isEnabled())
78        self.assertFalse(self.widget.removeButton.isEnabled())
79        self.assertTrue(self.widget.stopButton.isEnabled())
80        self.assertFalse(self.widget.stopButton.isVisible())
81        self.assertFalse(self.widget.regConstantSuggestionButton.isEnabled())
82        self.assertFalse(self.widget.noOfTermsSuggestionButton.isEnabled())
83        self.assertFalse(self.widget.explorerButton.isEnabled())
84        self.assertTrue(self.widget.helpButton.isEnabled())
85        # extra windows and charts
86        self.assertIsNone(self.widget.dmaxWindow)
87        self.assertIsNone(self.widget.prPlot)
88        self.assertIsNone(self.widget.dataPlot)
89        # threads
90        self.assertIsNone(self.widget.calcThread)
91        self.assertIsNone(self.widget.estimationThread)
92        self.assertIsNone(self.widget.estimationThreadNT)
93
94    def baseBatchState(self):
95        """ Testing the base batch fitting state """
96        self.assertTrue(self.widget.allowBatch())
97        self.assertFalse(self.widget.isBatch)
98        self.assertIsNone(self.widget.batchResultsWindow)
99        self.assertFalse(self.widget.calculateAllButton.isEnabled())
100        self.assertEqual(len(self.widget.batchResults), 0)
101        self.assertEqual(len(self.widget.batchComplete), 0)
102        self.widget.closeBatchResults()
103        self.assertIsNone(self.widget.batchResultsWindow)
104
105    def zeroDataSetState(self):
106        """ Testing the base data state of the GUI """
107        # data variables
108        self.assertIsNone(self.widget._data)
109        self.assertEqual(len(self.widget._dataList), 0)
110        self.assertEqual(self.widget.nTermsSuggested, 10)
111        # inputs
112        self.assertEqual(len(self.widget.dataList), 0)
113        self.assertEqual(self.widget.backgroundInput.text(), "0.0")
114        self.assertEqual(self.widget.minQInput.text(), "")
115        self.assertEqual(self.widget.maxQInput.text(), "")
116        self.assertEqual(self.widget.regularizationConstantInput.text(), "0.0001")
117        self.assertEqual(self.widget.noOfTermsInput.text(), "10")
118        self.assertEqual(self.widget.maxDistanceInput.text(), "140.0")
119
120    def oneDataSetState(self):
121        """ Testing the base data state of the GUI """
122        # Test the globals after first sent
123        self.assertEqual(len(self.widget._dataList), 1)
124        self.assertEqual(self.widget.dataList.count(), 1)
125        # See that the buttons are now enabled properly
126        self.widget.enableButtons()
127        self.assertFalse(self.widget.calculateAllButton.isEnabled())
128        self.assertTrue(self.widget.calculateThisButton.isEnabled())
129        self.assertTrue(self.widget.removeButton.isEnabled())
130        self.assertTrue(self.widget.explorerButton.isEnabled())
131
132    def twoDataSetState(self):
133        """ Testing the base data state of the GUI """
134        # Test the globals after first sent
135        self.assertEqual(len(self.widget._dataList), 2)
136        self.assertEqual(self.widget.dataList.count(), 2)
137        # See that the buttons are now enabled properly
138        self.widget.enableButtons()
139        self.assertTrue(self.widget.calculateThisButton.isEnabled())
140        self.assertTrue(self.widget.calculateAllButton.isEnabled())
141        self.assertTrue(self.widget.removeButton.isEnabled())
142        self.assertTrue(self.widget.explorerButton.isEnabled())
143
144    def testDefaults(self):
145        """ Test the GUI in its default state """
146        self.baseGUIState()
147        self.zeroDataSetState()
148        self.baseBatchState()
149        self.removeAllData()
150
151    def testAllowBatch(self):
152        """ Batch P(r) Tests """
153        self.baseBatchState()
154        self.widget.setData([self.fakeData1])
155        self.oneDataSetState()
156        self.widget.setData([self.fakeData2])
157        self.twoDataSetState()
158        self.widget.calculateAllButton.click()
159        self.assertTrue(self.widget.isCalculating)
160        self.assertTrue(self.widget.isBatch)
161        self.assertTrue(self.widget.stopButton.isVisible())
162        self.assertTrue(self.widget.stopButton.isEnabled())
163        self.assertIsNotNone(self.widget.batchResultsWindow)
164        self.assertTrue(self.widget.batchResultsWindow.cmdHelp.isEnabled())
165        self.assertEqual(self.widget.batchResultsWindow.tblParams.columnCount(), 9)
166        self.assertEqual(self.widget.batchResultsWindow.tblParams.rowCount(), 2)
167        # Test stop button
168        self.widget.stopButton.click()
169        self.assertTrue(self.widget.batchResultsWindow.isVisible())
170        self.assertFalse(self.widget.stopButton.isVisible())
171        self.assertTrue(self.widget.stopButton.isEnabled())
172        self.assertFalse(self.widget.isBatch)
173        self.assertFalse(self.widget.isCalculating)
174        self.widget.batchResultsWindow.close()
175        self.assertIsNone(self.widget.batchResultsWindow)
176        # Last test
177        self.removeAllData()
178        self.baseBatchState()
179
180    def testSetData(self):
181        """ Check if sending data works as expected """
182        self.zeroDataSetState()
183        self.widget.setData([self.fakeData1])
184        self.oneDataSetState()
185        self.widget.setData([self.fakeData1])
186        self.oneDataSetState()
187        self.widget.setData([self.fakeData2])
188        self.twoDataSetState()
189        self.removeAllData()
190        self.zeroDataSetState()
191        self.removeAllData()
192
193    def testRemoveData(self):
194        """ Test data removal from widget """
195        self.widget.setData([self.fakeData1, self.fakeData2])
196        self.twoDataSetState()
197        # Remove data 0
198        self.widget.removeData()
199        self.oneDataSetState()
200        self.removeAllData()
201
202    def testClose(self):
203        """ Test methods related to closing the window """
204        self.assertFalse(self.widget.isClosable())
205        self.widget.close()
206        self.assertTrue(self.widget.isMinimized())
207        self.assertIsNone(self.widget.dmaxWindow)
208        self.assertIsNone(self.widget.batchResultsWindow)
209        self.widget.setClosable(False)
210        self.assertFalse(self.widget.isClosable())
211        self.widget.close()
212        self.assertTrue(self.widget.isMinimized())
213        self.widget.setClosable(True)
214        self.assertTrue(self.widget.isClosable())
215        self.widget.setClosable()
216        self.assertTrue(self.widget.isClosable())
217        self.removeAllData()
218
219    def testGetNFunc(self):
220        """ test nfunc getter """
221        # Float
222        self.widget.noOfTermsInput.setText("10.0")
223        self.assertEqual(self.widget.getNFunc(), 10)
224        # Int
225        self.widget.noOfTermsInput.setText("980")
226        self.assertEqual(self.widget.getNFunc(), 980)
227        # Empty
228        with self.assertLogs(level='ERROR') as cm:
229            self.widget.noOfTermsInput.setText("")
230            n = self.widget.getNFunc()
231            self.assertEqual(cm.output, ['ERROR:sas.qtgui.Perspectives.Inversion.InversionPerspective:Incorrect number of terms specified: '])
232        self.assertEqual(self.widget.getNFunc(), 10)
233        # string
234        with self.assertLogs(level='ERROR') as cm:
235            self.widget.noOfTermsInput.setText("Nordvest Pizza")
236            n = self.widget.getNFunc()
237            self.assertEqual(cm.output, ['ERROR:sas.qtgui.Perspectives.Inversion.InversionPerspective:Incorrect number of terms specified: Nordvest Pizza'])
238        self.assertEqual(self.widget.getNFunc(), 10)
239        self.removeAllData()
240
241    def testSetCurrentData(self):
242        """ test current data setter """
243        self.widget.setData([self.fakeData1, self.fakeData2])
244
245        # Check that the current data is reference2
246        self.assertEqual(self.widget._data, self.fakeData2)
247        # Set the ref to none
248        self.widget.setCurrentData(None)
249        self.assertEqual(self.widget._data, self.fakeData2)
250        # Set the ref to wrong type
251        with self.assertRaises(AttributeError):
252            self.widget.setCurrentData("Afandi Kebab")
253        # Set the reference to ref1
254        self.widget.setCurrentData(self.fakeData1)
255        self.assertEqual(self.widget._data, self.fakeData1)
256        self.removeAllData()
257
258    def testModelChanged(self):
259        """ Test setting the input and the model and vice-versa """
260        # Initial values
261        self.assertEqual(self.widget._calculator.get_dmax(), 140.0)
262        self.assertEqual(self.widget._calculator.get_qmax(), -1.0)
263        self.assertEqual(self.widget._calculator.get_qmin(), -1.0)
264        self.assertEqual(self.widget._calculator.slit_height, 0.0)
265        self.assertEqual(self.widget._calculator.slit_width, 0.0)
266        self.assertEqual(self.widget._calculator.alpha, 0.0001)
267        # Set new values
268        self.widget.maxDistanceInput.setText("1.0")
269        self.widget.maxQInput.setText("3.0")
270        self.widget.minQInput.setText("5.0")
271        self.widget.slitHeightInput.setText("7.0")
272        self.widget.slitWidthInput.setText("9.0")
273        self.widget.regularizationConstantInput.setText("11.0")
274        # Check new values
275        self.assertEqual(self.widget._calculator.get_dmax(), 1.0)
276        self.assertEqual(self.widget._calculator.get_qmax(), 3.0)
277        self.assertEqual(self.widget._calculator.get_qmin(), 5.0)
278        self.assertEqual(self.widget._calculator.slit_height, 7.0)
279        self.assertEqual(self.widget._calculator.slit_width, 9.0)
280        self.assertEqual(self.widget._calculator.alpha, 11.0)
281        # Change model directly
282        self.widget.model.setItem(WIDGETS.W_MAX_DIST, QtGui.QStandardItem("2.0"))
283        self.widget.model.setItem(WIDGETS.W_QMIN, QtGui.QStandardItem("4.0"))
284        self.widget.model.setItem(WIDGETS.W_QMAX, QtGui.QStandardItem("6.0"))
285        self.widget.model.setItem(WIDGETS.W_SLIT_HEIGHT, QtGui.QStandardItem("8.0"))
286        self.widget.model.setItem(WIDGETS.W_SLIT_WIDTH, QtGui.QStandardItem("10.0"))
287        self.widget.model.setItem(WIDGETS.W_REGULARIZATION, QtGui.QStandardItem("12.0"))
288        # Check values
289        self.assertEqual(self.widget._calculator.get_dmax(), 2.0)
290        self.assertEqual(self.widget._calculator.get_qmin(), 4.0)
291        self.assertEqual(self.widget._calculator.get_qmax(), 6.0)
292        self.assertEqual(self.widget._calculator.slit_height, 8.0)
293        self.assertEqual(self.widget._calculator.slit_width, 10.0)
294        self.assertEqual(self.widget._calculator.alpha, 12.0)
295        self.removeAllData()
296
297    def testOpenExplorerWindow(self):
298        """ open Dx window """
299        self.assertIsNone(self.widget.dmaxWindow)
300        self.assertFalse(self.widget.explorerButton.isEnabled())
301        self.widget.openExplorerWindow()
302        self.assertIsNotNone(self.widget.dmaxWindow)
303        self.assertTrue(self.widget.dmaxWindow.isVisible())
304        self.assertTrue(self.widget.dmaxWindow.windowTitle() == "Dₐₓ Explorer")
305
306
307if __name__ == "__main__":
308    unittest.main()
Note: See TracBrowser for help on using the repository browser.